Decompiled source of K4os Compression LZ4 v1.3.9
K4os.Compression.LZ4.dll
Decompiled 10 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Buffers; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Threading; using K4os.Compression.LZ4.Engine; using K4os.Compression.LZ4.Internal; using Microsoft.CodeAnalysis; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = "")] [assembly: AssemblyCompany("Milosz Krajewski")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Milosz Krajewski")] [assembly: AssemblyDescription("Port of LZ4 compression algorithm for .NET")] [assembly: AssemblyFileVersion("1.3.8.0")] [assembly: AssemblyInformationalVersion("1.3.8")] [assembly: AssemblyProduct("K4os.Compression.LZ4")] [assembly: AssemblyTitle("K4os.Compression.LZ4")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/MiloszKrajewski/K4os.Compression.LZ4")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.3.8.0")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class IsUnmanagedAttribute : Attribute { } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace System { internal static class Extensions { internal static T Required<T>([NotNull] this T? value, [CallerArgumentExpression("value")] string name = null) { if (value != null) { return value; } return ThrowArgumentNullException<T>(name); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [Conditional("DEBUG")] public static void AssertTrue(this bool value, [CallerArgumentExpression("value")] string? name = null) { if (!value) { ThrowAssertionFailed(name); } } [MethodImpl(MethodImplOptions.NoInlining)] [DoesNotReturn] private static void ThrowAssertionFailed(string? name) { throw new ArgumentException((name ?? "<unknown>") + " assertion failed"); } [MethodImpl(MethodImplOptions.NoInlining)] [DoesNotReturn] private static T ThrowArgumentNullException<T>(string name) { throw new ArgumentNullException(name); } internal static void Validate<T>(this T[]? buffer, int offset, int length, bool allowNullIfEmpty = false) { if (!allowNullIfEmpty || buffer != null || offset != 0 || length != 0) { if (buffer == null) { throw new ArgumentNullException("buffer", "cannot be null"); } if (offset < 0 || length < 0 || offset + length > buffer.Length) { throw new ArgumentException($"invalid offset/length combination: {offset}/{length}"); } } } } } namespace System.Runtime.Versioning { [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class RequiresPreviewFeaturesAttribute : Attribute { public string? Message { get; } public string? Url { get; set; } public RequiresPreviewFeaturesAttribute() { } public RequiresPreviewFeaturesAttribute(string? message) { Message = message; } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class CallerArgumentExpressionAttribute : Attribute { public string ParameterName { get; } public CallerArgumentExpressionAttribute(string parameterName) { ParameterName = parameterName; } } [AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class CompilerFeatureRequiredAttribute : Attribute { public const string RefStructs = "RefStructs"; public const string RequiredMembers = "RequiredMembers"; public string FeatureName { get; } public bool IsOptional { get; set; } public CompilerFeatureRequiredAttribute(string featureName) { FeatureName = featureName; } } [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class InterpolatedStringHandlerArgumentAttribute : Attribute { public string[] Arguments { get; } public InterpolatedStringHandlerArgumentAttribute(string argument) { Arguments = new string[1] { argument }; } public InterpolatedStringHandlerArgumentAttribute(params string[] arguments) { Arguments = arguments; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class InterpolatedStringHandlerAttribute : Attribute { } [EditorBrowsable(EditorBrowsableState.Never)] [ExcludeFromCodeCoverage] internal static class IsExternalInit { } [AttributeUsage(AttributeTargets.Method, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class ModuleInitializerAttribute : Attribute { } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class RequiredMemberAttribute : Attribute { } [AttributeUsage(AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event | AttributeTargets.Interface, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class SkipLocalsInitAttribute : Attribute { } } namespace System.Diagnostics.CodeAnalysis { [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] [ExcludeFromCodeCoverage] internal sealed class MemberNotNullAttribute : Attribute { public string[] Members { get; } public MemberNotNullAttribute(string member) { Members = new string[1] { member }; } public MemberNotNullAttribute(params string[] members) { Members = members; } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] [ExcludeFromCodeCoverage] internal sealed class MemberNotNullWhenAttribute : Attribute { public bool ReturnValue { get; } public string[] Members { get; } public MemberNotNullWhenAttribute(bool returnValue, string member) { ReturnValue = returnValue; Members = new string[1] { member }; } public MemberNotNullWhenAttribute(bool returnValue, params string[] members) { ReturnValue = returnValue; Members = members; } } [AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class SetsRequiredMembersAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class StringSyntaxAttribute : Attribute { public const string CompositeFormat = "CompositeFormat"; public const string DateOnlyFormat = "DateOnlyFormat"; public const string DateTimeFormat = "DateTimeFormat"; public const string EnumFormat = "EnumFormat"; public const string GuidFormat = "GuidFormat"; public const string Json = "Json"; public const string NumericFormat = "NumericFormat"; public const string Regex = "Regex"; public const string TimeOnlyFormat = "TimeOnlyFormat"; public const string TimeSpanFormat = "TimeSpanFormat"; public const string Uri = "Uri"; public const string Xml = "Xml"; public string Syntax { get; } public object?[] Arguments { get; } public StringSyntaxAttribute(string syntax) { Syntax = syntax; Arguments = new object[0]; } public StringSyntaxAttribute(string syntax, params object?[] arguments) { Syntax = syntax; Arguments = arguments; } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class UnscopedRefAttribute : Attribute { } } namespace K4os.Compression.LZ4 { internal class AssemblyHook { private AssemblyHook() { } } public static class LZ4Codec { public const int Version = 192; public static bool Enforce32 { get { return LL.Enforce32; } set { LL.Enforce32 = value; } } public static int MaximumOutputSize(int length) { return LL.LZ4_compressBound(length); } public unsafe static int Encode(byte* source, int sourceLength, byte* target, int targetLength, LZ4Level level = LZ4Level.L00_FAST) { if (sourceLength <= 0) { return 0; } int num = ((level < LZ4Level.L03_HC) ? LLxx.LZ4_compress_fast(source, target, sourceLength, targetLength, 1) : LLxx.LZ4_compress_HC(source, target, sourceLength, targetLength, (int)level)); if (num > 0) { return num; } return -1; } public unsafe static int Encode(ReadOnlySpan<byte> source, Span<byte> target, LZ4Level level = LZ4Level.L00_FAST) { int length = source.Length; if (length <= 0) { return 0; } int length2 = target.Length; fixed (byte* source2 = source) { fixed (byte* target2 = target) { return Encode(source2, length, target2, length2, level); } } } public unsafe static int Encode(byte[] source, int sourceOffset, int sourceLength, byte[] target, int targetOffset, int targetLength, LZ4Level level = LZ4Level.L00_FAST) { source.Validate(sourceOffset, sourceLength); target.Validate(targetOffset, targetLength); fixed (byte* ptr = source) { fixed (byte* ptr2 = target) { return Encode(ptr + sourceOffset, sourceLength, ptr2 + targetOffset, targetLength, level); } } } public unsafe static int Decode(byte* source, int sourceLength, byte* target, int targetLength) { if (sourceLength <= 0) { return 0; } int num = LLxx.LZ4_decompress_safe(source, target, sourceLength, targetLength); if (num > 0) { return num; } return -1; } public unsafe static int PartialDecode(byte* source, int sourceLength, byte* target, int targetLength) { if (sourceLength <= 0) { return 0; } int num = LLxx.LZ4_decompress_safe_partial(source, target, sourceLength, targetLength); if (num > 0) { return num; } return -1; } public unsafe static int Decode(byte* source, int sourceLength, byte* target, int targetLength, byte* dictionary, int dictionaryLength) { if (sourceLength <= 0) { return 0; } int num = LLxx.LZ4_decompress_safe_usingDict(source, target, sourceLength, targetLength, dictionary, dictionaryLength); if (num > 0) { return num; } return -1; } public unsafe static int PartialDecode(ReadOnlySpan<byte> source, Span<byte> target) { int length = source.Length; if (length <= 0) { return 0; } fixed (byte* source2 = source) { fixed (byte* target2 = target) { return PartialDecode(source2, length, target2, target.Length); } } } public unsafe static int Decode(ReadOnlySpan<byte> source, Span<byte> target) { int length = source.Length; if (length <= 0) { return 0; } int length2 = target.Length; fixed (byte* source2 = source) { fixed (byte* target2 = target) { return Decode(source2, length, target2, length2); } } } public unsafe static int Decode(ReadOnlySpan<byte> source, Span<byte> target, ReadOnlySpan<byte> dictionary) { int length = source.Length; if (length <= 0) { return 0; } int length2 = target.Length; int length3 = dictionary.Length; fixed (byte* source2 = source) { fixed (byte* target2 = target) { fixed (byte* dictionary2 = dictionary) { return Decode(source2, length, target2, length2, dictionary2, length3); } } } } public unsafe static int Decode(byte[] source, int sourceOffset, int sourceLength, byte[] target, int targetOffset, int targetLength) { source.Validate(sourceOffset, sourceLength); target.Validate(targetOffset, targetLength); fixed (byte* ptr = source) { fixed (byte* ptr2 = target) { return Decode(ptr + sourceOffset, sourceLength, ptr2 + targetOffset, targetLength); } } } public unsafe static int Decode(byte[] source, int sourceOffset, int sourceLength, byte[] target, int targetOffset, int targetLength, byte[]? dictionary, int dictionaryOffset, int dictionaryLength) { source.Validate(sourceOffset, sourceLength); target.Validate(targetOffset, targetLength); dictionary.Validate(dictionaryOffset, dictionaryLength, allowNullIfEmpty: true); fixed (byte* ptr = source) { fixed (byte* ptr2 = target) { fixed (byte* ptr3 = dictionary) { return Decode(ptr + sourceOffset, sourceLength, ptr2 + targetOffset, targetLength, ptr3 + dictionaryOffset, dictionaryLength); } } } } } public enum LZ4Level { L00_FAST = 0, L03_HC = 3, L04_HC = 4, L05_HC = 5, L06_HC = 6, L07_HC = 7, L08_HC = 8, L09_HC = 9, L10_OPT = 10, L11_OPT = 11, L12_MAX = 12 } public static class LZ4Pickler { private const int MAX_STACKALLOC = 1024; private const byte VersionMask = 7; public static byte[] Pickle(byte[] source, LZ4Level level = LZ4Level.L00_FAST) { return Pickle(source.AsSpan(), level); } public static byte[] Pickle(byte[] source, int sourceIndex, int sourceLength, LZ4Level level = LZ4Level.L00_FAST) { return Pickle(source.AsSpan(sourceIndex, sourceLength), level); } public unsafe static byte[] Pickle(byte* source, int length, LZ4Level level = LZ4Level.L00_FAST) { return Pickle(new Span<byte>(source, length), level); } public static byte[] Pickle(ReadOnlySpan<byte> source, LZ4Level level = LZ4Level.L00_FAST) { int length = source.Length; if (length == 0) { return Mem.Empty; } if (length <= 1024) { Span<byte> buffer = stackalloc byte[1024]; return PickleWithBuffer(source, level, buffer); } PinnedMemory.Alloc(out var memory, length, zero: false); try { return PickleWithBuffer(source, level, memory.Span); } finally { memory.Free(); } } private static byte[] PickleWithBuffer(ReadOnlySpan<byte> source, LZ4Level level, Span<byte> buffer) { int length = source.Length; int num = LZ4Codec.Encode(source, buffer, level); if (num <= 0 || num >= length) { byte[] array = new byte[GetUncompressedHeaderSize(0, length) + length]; Span<byte> target = array.AsSpan(); int start = EncodeUncompressedHeader(target, 0, length); source.CopyTo(target.Slice(start)); return array; } int compressedHeaderSize = GetCompressedHeaderSize(0, length, num); byte[] array2 = new byte[compressedHeaderSize + num]; Span<byte> target2 = array2.AsSpan(); int start2 = EncodeCompressedHeader(target2, 0, compressedHeaderSize, length, num); buffer.Slice(0, num).CopyTo(target2.Slice(start2)); return array2; } public static void Pickle<TBufferWriter>(ReadOnlySpan<byte> source, TBufferWriter writer, LZ4Level level = LZ4Level.L00_FAST) where TBufferWriter : IBufferWriter<byte> { if (writer == null) { throw new ArgumentNullException("writer"); } int length = source.Length; if (length != 0) { int pessimisticHeaderSize = GetPessimisticHeaderSize(0, length); Span<byte> span = writer.GetSpan(pessimisticHeaderSize + length); int num = LZ4Codec.Encode(source, span.Slice(pessimisticHeaderSize, length), level); if (num <= 0 || num >= length) { int num2 = EncodeUncompressedHeader(span, 0, length); source.CopyTo(span.Slice(num2)); writer.Advance(num2 + length); } else { int num3 = EncodeCompressedHeader(span, 0, pessimisticHeaderSize, length, num); writer.Advance(num3 + num); } } } public static void Pickle(ReadOnlySpan<byte> source, IBufferWriter<byte> writer, LZ4Level level = LZ4Level.L00_FAST) { LZ4Pickler.Pickle<IBufferWriter<byte>>(source, writer, level); } private static int GetPessimisticHeaderSize(int version, int sourceLength) { if (version == 0) { return 1 + EffectiveSizeOf(sourceLength); } throw UnexpectedVersion(version); } private static int GetUncompressedHeaderSize(int version, int sourceLength) { if (version == 0) { return 1; } throw UnexpectedVersion(version); } private static int GetCompressedHeaderSize(int version, int sourceLength, int encodedLength) { if (version == 0) { return 1 + EffectiveSizeOf(sourceLength - encodedLength); } throw UnexpectedVersion(version); } private static int EncodeUncompressedHeader(Span<byte> target, int version, int sourceLength) { if (version == 0) { return EncodeUncompressedHeaderV0(target); } throw UnexpectedVersion(version); } private static int EncodeUncompressedHeaderV0(Span<byte> target) { target[0] = 0; return 1; } private static int EncodeCompressedHeader(Span<byte> target, int version, int headerSize, int sourceLength, int encodedLength) { if (version == 0) { return EncodeCompressedHeaderV0(target, headerSize, sourceLength, encodedLength); } throw UnexpectedVersion(version); } private static int EncodeCompressedHeaderV0(Span<byte> target, int headerSize, int sourceLength, int encodedLength) { int value = sourceLength - encodedLength; int num = headerSize - 1; target[0] = EncodeHeaderByteV0(num); PokeN(target.Slice(1), value, num); return 1 + num; } private unsafe static void PokeN(Span<byte> target, int value, int size) { if (size < 0 || size > 4 || target.Length < size) { throw new ArgumentException($"Unexpected size: {size}"); } Unsafe.CopyBlockUnaligned(ref target[0], ref *(byte*)(&value), (uint)size); } private static byte EncodeHeaderByteV0(int sizeOfDiff) { return (byte)(0u | (uint)((EncodeSizeOf(sizeOfDiff) & 3) << 6)); } private static int EffectiveSizeOf(int value) { if (value > 255) { if (value <= 65535) { return 2; } } else if (value >= 0) { return 1; } return 4; } private static int EncodeSizeOf(int size) { if (size == 4) { return 3; } return size; } private static Exception UnexpectedVersion(int version) { return new ArgumentException($"Unexpected pickle version: {version}"); } public static byte[] Unpickle(byte[] source) { return Unpickle(source.AsSpan()); } public static byte[] Unpickle(byte[] source, int index, int count) { return Unpickle(source.AsSpan(index, count)); } public unsafe static byte[] Unpickle(byte* source, int count) { return Unpickle(new Span<byte>(source, count)); } public static byte[] Unpickle(ReadOnlySpan<byte> source) { if (source.Length == 0) { return Mem.Empty; } PickleHeader header = DecodeHeader(source); int num = UnpickledSize(in header); if (num == 0) { return Mem.Empty; } byte[] array = new byte[num]; UnpickleCore(in header, source, array); return array; } public static void Unpickle<TBufferWriter>(ReadOnlySpan<byte> source, TBufferWriter writer) where TBufferWriter : IBufferWriter<byte> { writer.Required("writer"); if (source.Length != 0) { PickleHeader header = DecodeHeader(source); int num = UnpickledSize(in header); Span<byte> target = writer.GetSpan(num).Slice(0, num); UnpickleCore(in header, source, target); writer.Advance(num); } } public static void Unpickle(ReadOnlySpan<byte> source, IBufferWriter<byte> writer) { LZ4Pickler.Unpickle<IBufferWriter<byte>>(source, writer); } public static int UnpickledSize(ReadOnlySpan<byte> source) { PickleHeader header = DecodeHeader(source); return UnpickledSize(in header); } private static int UnpickledSize(in PickleHeader header) { return header.ResultLength; } public static void Unpickle(ReadOnlySpan<byte> source, Span<byte> output) { if (source.Length != 0) { PickleHeader header = DecodeHeader(source); UnpickleCore(in header, source, output); } } private static void UnpickleCore(in PickleHeader header, ReadOnlySpan<byte> source, Span<byte> target) { ReadOnlySpan<byte> source2 = source.Slice(header.DataOffset); int num = UnpickledSize(in header); int length = target.Length; if (length != num) { throw CorruptedPickle($"Output buffer size ({length}) does not match expected value ({num})"); } if (!header.IsCompressed) { source2.CopyTo(target); return; } int num2 = LZ4Codec.Decode(source2, target); if (num2 == num) { return; } throw CorruptedPickle($"Expected to decode {num} bytes but {num2} has been decoded"); } private static PickleHeader DecodeHeader(ReadOnlySpan<byte> source) { int num = source[0] & 7; if (num == 0) { return DecodeHeaderV0(source); } throw CorruptedPickle($"Version {num} is not recognized"); } private static PickleHeader DecodeHeaderV0(ReadOnlySpan<byte> source) { int num = (source[0] >> 6) & 3; int num2 = ((num != 3) ? num : 4); int num3 = num2; ushort num4 = (ushort)(1 + num3); int num5 = source.Length - num4; if (num5 < 0) { throw CorruptedPickle($"Unexpected data length: {num5}"); } int num6 = ((num3 != 0) ? PeekN(source.Slice(1), num3) : 0); int resultLength = num5 + num6; return new PickleHeader(num4, resultLength, num6 != 0); } private unsafe static int PeekN(ReadOnlySpan<byte> bytes, int size) { int result = 0; if (size < 0 || size > 4 || size > bytes.Length) { throw CorruptedPickle($"Unexpected field size: {size}"); } fixed (byte* source = bytes) { Unsafe.CopyBlockUnaligned(&result, source, (uint)size); } return result; } private static Exception CorruptedPickle(string message) { return new InvalidDataException("Pickle is corrupted: " + message); } } [StructLayout(LayoutKind.Sequential, Pack = 1)] internal readonly struct PickleHeader { public ushort DataOffset { get; } public ushort Flags { get; } public int ResultLength { get; } public bool IsCompressed => (Flags & 1) != 0; public PickleHeader(ushort dataOffset, int resultLength, bool compressed) { DataOffset = dataOffset; ResultLength = resultLength; Flags = (ushort)((compressed ? 1u : 0u) | 0u); } } } namespace K4os.Compression.LZ4.Internal { public static class BufferPool { public const int MinPooledSize = 512; [MethodImpl(MethodImplOptions.AggressiveInlining)] private static bool ShouldBePooled(int length) { return length >= 512; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static byte[] Rent(int size, bool zero) { byte[] array = ArrayPool<byte>.Shared.Rent(size); if (zero) { array.AsSpan(0, size).Clear(); } return array; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static byte[] Alloc(int size, bool zero = false) { if (!ShouldBePooled(size)) { return new byte[size]; } return Rent(size, zero); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsPooled(byte[] buffer) { return ShouldBePooled(buffer.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Free(byte[]? buffer) { if (buffer != null && IsPooled(buffer)) { ArrayPool<byte>.Shared.Return(buffer); } } } public class Mem { public const int K1 = 1024; public const int K2 = 2048; public const int K4 = 4096; public const int K8 = 8192; public const int K16 = 16384; public const int K32 = 32768; public const int K64 = 65536; public const int K128 = 131072; public const int K256 = 262144; public const int K512 = 524288; public const int M1 = 1048576; public const int M4 = 4194304; public static readonly byte[] Empty = Array.Empty<byte>(); public unsafe static bool System32 { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return sizeof(void*) < 8; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int RoundUp(int value, int step) { return (value + step - 1) / step * step; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal unsafe static void CpBlk(void* target, void* source, uint length) { Unsafe.CopyBlockUnaligned(target, source, length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal unsafe static void ZBlk(void* target, byte value, uint length) { Unsafe.InitBlockUnaligned(target, value, length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static void Copy(byte* target, byte* source, int length) { if (length > 0) { CpBlk(target, source, (uint)length); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static void Move(byte* target, byte* source, int length) { Buffer.MemoryCopy(source, target, length, length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static void* Alloc(int size) { return Marshal.AllocHGlobal(size).ToPointer(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static byte* Zero(byte* target, int length) { return Fill(target, 0, length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static byte* Fill(byte* target, byte value, int length) { if (length > 0) { ZBlk(target, value, (uint)length); } return target; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static void* AllocZero(int size) { return Zero((byte*)Alloc(size), size); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static void Free(void* ptr) { Marshal.FreeHGlobal(new IntPtr(ptr)); } public unsafe static T* CloneArray<T>(T[] array) where T : unmanaged { int num = Unsafe.SizeOf<T>() * array.Length; void* intPtr = Alloc(num); fixed (byte* ptr = &Unsafe.As<T, byte>(ref array[0])) { void* source = ptr; Copy((byte*)intPtr, (byte*)source, num); } return (T*)intPtr; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static byte Peek1(void* p) { return *(byte*)p; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static void Poke1(void* p, byte v) { *(byte*)p = v; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static ushort Peek2(void* p) { ushort result = default(ushort); CpBlk(&result, p, 2u); return result; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static void Poke2(void* p, ushort v) { CpBlk(p, &v, 2u); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static uint Peek4(void* p) { uint result = default(uint); CpBlk(&result, p, 4u); return result; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static void Poke4(void* p, uint v) { CpBlk(p, &v, 4u); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static ulong Peek8(void* p) { ulong result = default(ulong); CpBlk(&result, p, 8u); return result; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static void Poke8(void* p, ulong v) { CpBlk(p, &v, 8u); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static void Copy1(byte* target, byte* source) { *target = *source; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static void Copy2(byte* target, byte* source) { CpBlk(target, source, 2u); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static void Copy4(byte* target, byte* source) { CpBlk(target, source, 4u); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static void Copy8(byte* target, byte* source) { CpBlk(target, source, 8u); } } public struct PinnedMemory { private unsafe byte* _pointer; private GCHandle _handle; private int _size; public static int MaxPooledSize { get; set; } = 1048576; public unsafe readonly byte* Pointer { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return _pointer; } } public unsafe Span<byte> Span { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Span<byte>(Pointer, _size); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe readonly T* Reference<T>() where T : unmanaged { return (T*)_pointer; } public static PinnedMemory Alloc(int size, bool zero = true) { Alloc(out var memory, size, zero); return memory; } public static void Alloc(out PinnedMemory memory, int size, bool zero = true) { if (size <= 0) { throw new ArgumentOutOfRangeException("size"); } if (size > MaxPooledSize) { AllocateNative(out memory, size, zero); } else { RentManagedFromPool(out memory, size, zero); } } public unsafe static void Alloc<T>(out PinnedMemory memory, bool zero = true) where T : unmanaged { Alloc(out memory, sizeof(T), zero); } private unsafe static void AllocateNative(out PinnedMemory memory, int size, bool zero) { void* pointer = (zero ? Mem.AllocZero(size) : Mem.Alloc(size)); GC.AddMemoryPressure(size); memory._pointer = (byte*)pointer; memory._handle = default(GCHandle); memory._size = size; } private unsafe static void RentManagedFromPool(out PinnedMemory memory, int size, bool zero) { GCHandle handle = GCHandle.Alloc(BufferPool.Alloc(size, zero), GCHandleType.Pinned); byte* pointer = (byte*)(void*)handle.AddrOfPinnedObject(); memory._pointer = pointer; memory._handle = handle; memory._size = size; } public unsafe void Clear() { if (_size > 0 && _pointer != null) { Mem.Zero(_pointer, _size); } } public unsafe void Free() { if (_handle.IsAllocated) { ReleaseManaged(); } else if (_pointer != null) { ReleaseNative(); } ClearFields(); } private void ReleaseManaged() { byte[] buffer = (_handle.IsAllocated ? ((byte[])_handle.Target) : null); _handle.Free(); BufferPool.Free(buffer); } private unsafe void ReleaseNative() { GC.RemoveMemoryPressure(_size); Mem.Free(_pointer); } private unsafe void ClearFields() { _pointer = null; _handle = default(GCHandle); _size = 0; } } public abstract class UnmanagedResources : IDisposable { private int _disposed; public bool IsDisposed => Interlocked.CompareExchange(ref _disposed, 0, 0) != 0; protected void ThrowIfDisposed() { if (IsDisposed) { throw new ObjectDisposedException(GetType().FullName + " is already disposed"); } } protected virtual void ReleaseUnmanaged() { } protected virtual void ReleaseManaged() { } protected virtual void Dispose(bool disposing) { if (Interlocked.CompareExchange(ref _disposed, 1, 0) == 0) { ReleaseUnmanaged(); if (disposing) { ReleaseManaged(); } } } public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } ~UnmanagedResources() { Dispose(disposing: false); } } public class Mem32 : Mem { [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static uint PeekW(void* p) { return Mem.Peek4(p); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static void PokeW(void* p, uint v) { Mem.Poke4(p, v); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static void Copy16(byte* target, byte* source) { Mem.Copy8(target, source); Mem.Copy8(target + 8, source + 8); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static void Copy18(byte* target, byte* source) { Mem.Copy8(target, source); Mem.Copy8(target + 8, source + 8); Mem.Copy2(target + 16, source + 16); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static void WildCopy8(byte* target, byte* source, void* limit) { do { Mem.Copy8(target, source); target += 8; source += 8; } while (target < limit); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static void WildCopy32(byte* target, byte* source, void* limit) { do { Copy16(target, source); Copy16(target + 16, source + 16); target += 32; source += 32; } while (target < limit); } } public class Mem64 : Mem { [MethodImpl(MethodImplOptions.AggressiveInlining)] public new unsafe static ushort Peek2(void* p) { return *(ushort*)p; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public new unsafe static void Poke2(void* p, ushort v) { *(ushort*)p = v; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public new unsafe static uint Peek4(void* p) { return *(uint*)p; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public new unsafe static void Poke4(void* p, uint v) { *(uint*)p = v; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public new unsafe static void Copy1(byte* target, byte* source) { *target = *source; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public new unsafe static void Copy2(byte* target, byte* source) { *(short*)target = *(short*)source; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public new unsafe static void Copy4(byte* target, byte* source) { *(int*)target = *(int*)source; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public new unsafe static ulong Peek8(void* p) { return *(ulong*)p; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public new unsafe static void Poke8(void* p, ulong v) { *(ulong*)p = v; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public new unsafe static void Copy8(byte* target, byte* source) { *(long*)target = *(long*)source; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static ulong PeekW(void* p) { return Peek8(p); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static void PokeW(void* p, ulong v) { Poke8(p, v); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static void Copy16(byte* target, byte* source) { Copy8(target, source); Copy8(target + 8, source + 8); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static void Copy18(byte* target, byte* source) { Copy8(target, source); Copy8(target + 8, source + 8); Copy2(target + 16, source + 16); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static void WildCopy8(byte* target, byte* source, void* limit) { do { Copy8(target, source); target += 8; source += 8; } while (target < limit); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static void WildCopy32(byte* target, byte* source, void* limit) { do { Copy16(target, source); Copy16(target + 16, source + 16); target += 32; source += 32; } while (target < limit); } } } namespace K4os.Compression.LZ4.Engine { public enum Algorithm { X32, X64 } internal class LL { public struct LZ4_stream_t { public unsafe fixed uint hashTable[4096]; public uint currentOffset; public bool dirty; public tableType_t tableType; public unsafe byte* dictionary; public unsafe LZ4_stream_t* dictCtx; public uint dictSize; } public struct LZ4_streamDecode_t { public unsafe byte* externalDict; public uint extDictSize; public unsafe byte* prefixEnd; public uint prefixSize; } public enum limitedOutput_directive { notLimited, limitedOutput, fillOutput } public enum tableType_t { clearedTable, byPtr, byU32, byU16 } public enum dict_directive { noDict, withPrefix64k, usingExtDict, usingDictCtx } public enum dictIssue_directive { noDictIssue, dictSmall } public enum endCondition_directive { endOnOutputSize, endOnInputSize } public enum earlyEnd_directive { full, partial } protected enum variable_length_error { loop_error = -2, initial_error, ok } public enum dictCtx_directive { noDictCtx, usingDictCtxHc } public struct LZ4_streamHC_t { public unsafe fixed uint hashTable[32768]; public unsafe fixed ushort chainTable[65536]; public unsafe byte* end; public unsafe byte* @base; public unsafe byte* dictBase; public uint dictLimit; public uint lowLimit; public uint nextToUpdate; public short compressionLevel; public bool favorDecSpeed; public bool dirty; public unsafe LZ4_streamHC_t* dictCtx; } protected enum repeat_state_e { rep_untested, rep_not, rep_confirmed } public enum HCfavor_e { favorCompressionRatio, favorDecompressionSpeed } public struct LZ4HC_match_t { public int off; public int len; } public struct LZ4HC_optimal_t { public int price; public int off; public int mlen; public int litlen; } public enum lz4hc_strat_e { lz4hc, lz4opt } public struct cParams_t { public lz4hc_strat_e strat; public uint nbSearches; public uint targetLength; public cParams_t(lz4hc_strat_e strat, uint nbSearches, uint targetLength) { this.strat = strat; this.nbSearches = nbSearches; this.targetLength = targetLength; } } private static readonly uint[] _inc32table = new uint[8] { 0u, 1u, 2u, 1u, 0u, 4u, 4u, 4u }; private static readonly int[] _dec64table = new int[8] { 0, 0, 0, -1, -4, 1, 2, 3 }; protected unsafe static readonly uint* inc32table = Mem.CloneArray(_inc32table); protected unsafe static readonly int* dec64table = Mem.CloneArray(_dec64table); protected const int LZ4_MEMORY_USAGE = 14; protected const int LZ4_MAX_INPUT_SIZE = 2113929216; protected const int LZ4_DISTANCE_MAX = 65535; protected const int LZ4_DISTANCE_ABSOLUTE_MAX = 65535; protected const int LZ4_HASHLOG = 12; protected const int LZ4_HASHTABLESIZE = 16384; protected const int LZ4_HASH_SIZE_U32 = 4096; protected const int ACCELERATION_DEFAULT = 1; protected const int MINMATCH = 4; protected const int WILDCOPYLENGTH = 8; protected const int LASTLITERALS = 5; protected const int MFLIMIT = 12; protected const int MATCH_SAFEGUARD_DISTANCE = 12; protected const int FASTLOOP_SAFE_DISTANCE = 64; protected const int LZ4_minLength = 13; protected const int KB = 1024; protected const int MB = 1048576; protected const uint GB = 1073741824u; protected const int ML_BITS = 4; protected const uint ML_MASK = 15u; protected const int RUN_BITS = 4; protected const uint RUN_MASK = 15u; protected const int OPTIMAL_ML = 18; protected const int LZ4_OPT_NUM = 4096; protected const int LZ4_64Klimit = 65547; protected const int LZ4_skipTrigger = 6; protected const int LZ4HC_DICTIONARY_LOGSIZE = 16; protected const int LZ4HC_MAXD = 65536; protected const int LZ4HC_MAXD_MASK = 65535; protected const int LZ4HC_HASH_LOG = 15; protected const int LZ4HC_HASHTABLESIZE = 32768; protected const int LZ4HC_HASH_MASK = 32767; protected const int LZ4HC_CLEVEL_MIN = 3; protected const int LZ4HC_CLEVEL_DEFAULT = 9; protected const int LZ4HC_CLEVEL_OPT_MIN = 10; protected const int LZ4HC_CLEVEL_MAX = 12; public static bool Enforce32 { get; set; } = false; public static Algorithm Algorithm { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { if (!Enforce32 && !Mem.System32) { return Algorithm.X64; } return Algorithm.X32; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static int LZ4_sizeofStateHC() { return sizeof(LZ4_streamHC_t); } public unsafe static void LZ4_setCompressionLevel(LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel) { if (compressionLevel < 1) { compressionLevel = 9; } if (compressionLevel > 12) { compressionLevel = 12; } LZ4_streamHCPtr->compressionLevel = (short)compressionLevel; } public unsafe static void LZ4_favorDecompressionSpeed(LZ4_streamHC_t* LZ4_streamHCPtr, int favor) { LZ4_streamHCPtr->favorDecSpeed = favor != 0; } public unsafe static LZ4_streamHC_t* LZ4_initStreamHC(void* buffer, int size) { if (buffer == null) { return null; } if (size < sizeof(LZ4_streamHC_t)) { return null; } ((LZ4_streamHC_t*)buffer)->end = (byte*)(-1); ((LZ4_streamHC_t*)buffer)->@base = null; ((LZ4_streamHC_t*)buffer)->dictCtx = null; ((LZ4_streamHC_t*)buffer)->favorDecSpeed = false; ((LZ4_streamHC_t*)buffer)->dirty = false; LZ4_setCompressionLevel((LZ4_streamHC_t*)buffer, 9); return (LZ4_streamHC_t*)buffer; } public unsafe static LZ4_streamHC_t* LZ4_initStreamHC(LZ4_streamHC_t* stream) { return LZ4_initStreamHC(stream, sizeof(LZ4_streamHC_t)); } public unsafe static void LZ4_resetStreamHC_fast(LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel) { if (LZ4_streamHCPtr->dirty) { LZ4_initStreamHC(LZ4_streamHCPtr); } else { byte** end = &LZ4_streamHCPtr->end; *end -= LZ4_streamHCPtr->@base; LZ4_streamHCPtr->@base = null; LZ4_streamHCPtr->dictCtx = null; } LZ4_setCompressionLevel(LZ4_streamHCPtr, compressionLevel); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static uint HASH_FUNCTION(uint value) { return (uint)((int)value * -1640531535) >> 17; } [MethodImpl(MethodImplOptions.AggressiveInlining)] protected unsafe static ref ushort DELTANEXTU16(ushort* table, uint pos) { return ref table[(int)(ushort)pos]; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static uint LZ4HC_hashPtr(void* ptr) { return HASH_FUNCTION(Mem.Peek4(ptr)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static void LZ4HC_Insert(LZ4_streamHC_t* hc4, byte* ip) { ushort* table = hc4->chainTable; uint* ptr = hc4->hashTable; byte* @base = hc4->@base; uint num = (uint)(ip - @base); for (uint num2 = hc4->nextToUpdate; num2 < num; num2++) { uint num3 = LZ4HC_hashPtr(@base + num2); uint num4 = num2 - ptr[num3]; if (num4 > 65535) { num4 = 65535u; } DELTANEXTU16(table, num2) = (ushort)num4; ptr[num3] = num2; } hc4->nextToUpdate = num; } public unsafe static void LZ4HC_setExternalDict(LZ4_streamHC_t* ctxPtr, byte* newBlock) { if (ctxPtr->end >= ctxPtr->@base + ctxPtr->dictLimit + 4) { LZ4HC_Insert(ctxPtr, ctxPtr->end - 3); } ctxPtr->lowLimit = ctxPtr->dictLimit; ctxPtr->dictLimit = (uint)(ctxPtr->end - ctxPtr->@base); ctxPtr->dictBase = ctxPtr->@base; ctxPtr->@base = newBlock - ctxPtr->dictLimit; ctxPtr->end = newBlock; ctxPtr->nextToUpdate = ctxPtr->dictLimit; ctxPtr->dictCtx = null; } public unsafe static void LZ4HC_clearTables(LZ4_streamHC_t* hc4) { Mem.Fill((byte*)hc4->hashTable, 0, 131072); Mem.Fill((byte*)hc4->chainTable, byte.MaxValue, 131072); } public unsafe static void LZ4HC_init_internal(LZ4_streamHC_t* hc4, byte* start) { long num = hc4->end - hc4->@base; if (num < 0 || num > 1073741824) { LZ4HC_clearTables(hc4); num = 0L; } num += 65536; hc4->nextToUpdate = (uint)num; hc4->@base = start - num; hc4->end = start; hc4->dictBase = start - num; hc4->dictLimit = (uint)num; hc4->lowLimit = (uint)num; } public unsafe static int LZ4_saveDictHC(LZ4_streamHC_t* LZ4_streamHCPtr, byte* safeBuffer, int dictSize) { int num = (int)(LZ4_streamHCPtr->end - (LZ4_streamHCPtr->@base + LZ4_streamHCPtr->dictLimit)); if (dictSize > 65536) { dictSize = 65536; } if (dictSize < 4) { dictSize = 0; } if (dictSize > num) { dictSize = num; } Mem.Move(safeBuffer, LZ4_streamHCPtr->end - dictSize, dictSize); uint num2 = (uint)(LZ4_streamHCPtr->end - LZ4_streamHCPtr->@base); LZ4_streamHCPtr->end = safeBuffer + dictSize; LZ4_streamHCPtr->@base = LZ4_streamHCPtr->end - num2; LZ4_streamHCPtr->dictLimit = num2 - (uint)dictSize; LZ4_streamHCPtr->lowLimit = num2 - (uint)dictSize; if (LZ4_streamHCPtr->nextToUpdate < LZ4_streamHCPtr->dictLimit) { LZ4_streamHCPtr->nextToUpdate = LZ4_streamHCPtr->dictLimit; } return dictSize; } public unsafe static int LZ4_loadDictHC(LZ4_streamHC_t* LZ4_streamHCPtr, byte* dictionary, int dictSize) { if (dictSize > 65536) { dictionary += dictSize - 65536; dictSize = 65536; } int compressionLevel = LZ4_streamHCPtr->compressionLevel; LZ4_initStreamHC(LZ4_streamHCPtr); LZ4_setCompressionLevel(LZ4_streamHCPtr, compressionLevel); LZ4HC_init_internal(LZ4_streamHCPtr, dictionary); LZ4_streamHCPtr->end = dictionary + dictSize; if (dictSize >= 4) { LZ4HC_Insert(LZ4_streamHCPtr, LZ4_streamHCPtr->end - 3); } return dictSize; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint LZ4HC_rotl32(uint x, int r) { return (x << r) | (x >> 32 - r); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool LZ4HC_protectDictEnd(uint dictLimit, uint matchIndex) { return dictLimit - 1 - matchIndex >= 3; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static int LZ4HC_countBack(byte* ip, byte* match, byte* iMin, byte* mMin) { int num = 0; int num2 = (int)MAX(iMin - ip, mMin - match); while (num > num2 && ip[num - 1] == match[num - 1]) { num--; } return num; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static uint LZ4HC_reverseCountPattern(byte* ip, byte* iLow, uint pattern) { byte* ptr = ip; while (ip >= iLow + 4 && Mem.Peek4(ip - 4) == pattern) { ip -= 4; } byte* ptr2 = (byte*)(&pattern) + 3; while (ip > iLow && ip[-1] == *ptr2) { ip--; ptr2--; } return (uint)(ptr - ip); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint LZ4HC_rotatePattern(uint rotate, uint pattern) { uint num = (rotate & 3) << 3; if (num == 0) { return pattern; } return LZ4HC_rotl32(pattern, (int)num); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LZ4HC_literalsPrice(int litlen) { int num = litlen; if (litlen >= 15) { num += 1 + (litlen - 15) / 255; } return num; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LZ4HC_sequencePrice(int litlen, int mlen) { int num = 3; num += LZ4HC_literalsPrice(litlen); if (mlen >= 19) { num += 1 + (mlen - 19) / 255; } return num; } [MethodImpl(MethodImplOptions.AggressiveInlining)] [Conditional("DEBUG")] public static void Assert(bool value, [CallerArgumentExpression("value")] string message = null) { } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static int LZ4_compressBound(int isize) { if (isize <= 2113929216) { return isize + isize / 255 + 16; } return 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static int LZ4_decoderRingBufferSize(int isize) { return 65550 + isize; } [MethodImpl(MethodImplOptions.AggressiveInlining)] protected static uint LZ4_hash4(uint sequence, tableType_t tableType) { int num = ((tableType == tableType_t.byU16) ? 13 : 12); return (uint)((int)sequence * -1640531535) >> 32 - num; } [MethodImpl(MethodImplOptions.AggressiveInlining)] protected static uint LZ4_hash5(ulong sequence, tableType_t tableType) { int num = ((tableType == tableType_t.byU16) ? 13 : 12); return (uint)((sequence << 24) * 889523592379L >> 64 - num); } [MethodImpl(MethodImplOptions.AggressiveInlining)] protected unsafe static void LZ4_clearHash(uint h, void* tableBase, tableType_t tableType) { switch (tableType) { case tableType_t.byPtr: *(IntPtr*)((byte*)tableBase + h * sizeof(byte*)) = (nint)0; break; case tableType_t.byU32: *(int*)((byte*)tableBase + (long)h * 4L) = 0; break; case tableType_t.byU16: *(short*)((byte*)tableBase + (long)h * 2L) = 0; break; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] protected unsafe static void LZ4_putIndexOnHash(uint idx, uint h, void* tableBase, tableType_t tableType) { switch (tableType) { case tableType_t.byU32: *(uint*)((byte*)tableBase + (long)h * 4L) = idx; break; case tableType_t.byU16: *(ushort*)((byte*)tableBase + (long)h * 2L) = (ushort)idx; break; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] protected unsafe static void LZ4_putPositionOnHash(byte* p, uint h, void* tableBase, tableType_t tableType, byte* srcBase) { switch (tableType) { case tableType_t.byPtr: *(byte**)((byte*)tableBase + h * sizeof(byte*)) = p; break; case tableType_t.byU32: *(int*)((byte*)tableBase + (long)h * 4L) = (int)(p - srcBase); break; case tableType_t.byU16: *(ushort*)((byte*)tableBase + (long)h * 2L) = (ushort)(p - srcBase); break; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] protected unsafe static uint LZ4_getIndexOnHash(uint h, void* tableBase, tableType_t tableType) { return tableType switch { tableType_t.byU32 => *(uint*)((byte*)tableBase + (long)h * 4L), tableType_t.byU16 => *(ushort*)((byte*)tableBase + (long)h * 2L), _ => 0u, }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] protected unsafe static byte* LZ4_getPositionOnHash(uint h, void* tableBase, tableType_t tableType, byte* srcBase) { return tableType switch { tableType_t.byPtr => *(byte**)((byte*)tableBase + h * sizeof(byte*)), tableType_t.byU32 => (uint)(*(int*)((byte*)tableBase + (long)h * 4L)) + srcBase, _ => (int)(*(ushort*)((byte*)tableBase + (long)h * 2L)) + srcBase, }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int MIN(int a, int b) { if (a >= b) { return b; } return a; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint MIN(uint a, uint b) { if (a >= b) { return b; } return a; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint MAX(uint a, uint b) { if (a >= b) { return a; } return b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long MAX(long a, long b) { if (a >= b) { return a; } return b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long MIN(long a, long b) { if (a >= b) { return b; } return a; } [MethodImpl(MethodImplOptions.AggressiveInlining)] protected unsafe static uint LZ4_readVLE(byte** ip, byte* lencheck, bool loop_check, bool initial_check, variable_length_error* error) { uint num = 0u; if (initial_check && *ip >= lencheck) { *error = variable_length_error.initial_error; return num; } uint num2; do { num2 = *(*ip); (*ip)++; num += num2; if (loop_check && *ip >= lencheck) { *error = variable_length_error.loop_error; return num; } } while (num2 == 255); return num; } public unsafe static int LZ4_saveDict(LZ4_stream_t* LZ4_dict, byte* safeBuffer, int dictSize) { byte* ptr = LZ4_dict->dictionary + LZ4_dict->dictSize; if ((uint)dictSize > 65536u) { dictSize = 65536; } if ((uint)dictSize > LZ4_dict->dictSize) { dictSize = (int)LZ4_dict->dictSize; } Mem.Move(safeBuffer, ptr - dictSize, dictSize); LZ4_dict->dictionary = safeBuffer; LZ4_dict->dictSize = (uint)dictSize; return dictSize; } public unsafe static LZ4_stream_t* LZ4_initStream(LZ4_stream_t* buffer) { Mem.Zero((byte*)buffer, sizeof(LZ4_stream_t)); return buffer; } public unsafe static void LZ4_setStreamDecode(LZ4_streamDecode_t* LZ4_streamDecode, byte* dictionary, int dictSize) { LZ4_streamDecode->prefixSize = (uint)dictSize; LZ4_streamDecode->prefixEnd = dictionary + dictSize; LZ4_streamDecode->externalDict = null; LZ4_streamDecode->extDictSize = 0u; } } internal static class LLxx { private static NotImplementedException AlgorithmNotImplemented(string action) { return new NotImplementedException($"Algorithm {LL.Algorithm} not implemented for {action}"); } [MethodImpl(MethodImplOptions.NoInlining)] public unsafe static int LZ4_decompress_safe(byte* source, byte* target, int sourceLength, int targetLength) { return LL.Algorithm switch { Algorithm.X64 => LL64.LZ4_decompress_safe(source, target, sourceLength, targetLength), Algorithm.X32 => LL32.LZ4_decompress_safe(source, target, sourceLength, targetLength), _ => throw AlgorithmNotImplemented("LZ4_decompress_safe"), }; } [MethodImpl(MethodImplOptions.NoInlining)] public unsafe static int LZ4_decompress_safe_partial(byte* source, byte* target, int sourceLength, int targetLength) { return LL.Algorithm switch { Algorithm.X64 => LL64.LZ4_decompress_safe_partial(source, target, sourceLength, targetLength, targetLength), Algorithm.X32 => LL32.LZ4_decompress_safe_partial(source, target, sourceLength, targetLength, targetLength), _ => throw AlgorithmNotImplemented("LZ4_decompress_safe_partial"), }; } [MethodImpl(MethodImplOptions.NoInlining)] public unsafe static int LZ4_decompress_safe_usingDict(byte* source, byte* target, int sourceLength, int targetLength, byte* dictionary, int dictionaryLength) { return LL.Algorithm switch { Algorithm.X64 => LL64.LZ4_decompress_safe_usingDict(source, target, sourceLength, targetLength, dictionary, dictionaryLength), Algorithm.X32 => LL32.LZ4_decompress_safe_usingDict(source, target, sourceLength, targetLength, dictionary, dictionaryLength), _ => throw AlgorithmNotImplemented("LZ4_decompress_safe_usingDict"), }; } [MethodImpl(MethodImplOptions.NoInlining)] public unsafe static int LZ4_decompress_safe_continue(LL.LZ4_streamDecode_t* context, byte* source, byte* target, int sourceLength, int targetLength) { return LL.Algorithm switch { Algorithm.X64 => LL64.LZ4_decompress_safe_continue(context, source, target, sourceLength, targetLength), Algorithm.X32 => LL32.LZ4_decompress_safe_continue(context, source, target, sourceLength, targetLength), _ => throw AlgorithmNotImplemented("LZ4_decompress_safe_continue"), }; } [MethodImpl(MethodImplOptions.NoInlining)] public unsafe static int LZ4_compress_fast(byte* source, byte* target, int sourceLength, int targetLength, int acceleration) { return LL.Algorithm switch { Algorithm.X64 => LL64.LZ4_compress_fast(source, target, sourceLength, targetLength, acceleration), Algorithm.X32 => LL32.LZ4_compress_fast(source, target, sourceLength, targetLength, acceleration), _ => throw AlgorithmNotImplemented("LZ4_compress_fast"), }; } [MethodImpl(MethodImplOptions.NoInlining)] public unsafe static int LZ4_compress_fast_continue(LL.LZ4_stream_t* context, byte* source, byte* target, int sourceLength, int targetLength, int acceleration) { return LL.Algorithm switch { Algorithm.X64 => LL64.LZ4_compress_fast_continue(context, source, target, sourceLength, targetLength, acceleration), Algorithm.X32 => LL32.LZ4_compress_fast_continue(context, source, target, sourceLength, targetLength, acceleration), _ => throw AlgorithmNotImplemented("LZ4_compress_fast_continue"), }; } [MethodImpl(MethodImplOptions.NoInlining)] public unsafe static int LZ4_compress_HC(byte* source, byte* target, int sourceLength, int targetLength, int level) { return LL.Algorithm switch { Algorithm.X64 => LL64.LZ4_compress_HC(source, target, sourceLength, targetLength, level), Algorithm.X32 => LL32.LZ4_compress_HC(source, target, sourceLength, targetLength, level), _ => throw AlgorithmNotImplemented("LZ4_compress_HC"), }; } [MethodImpl(MethodImplOptions.NoInlining)] public unsafe static int LZ4_compress_HC_continue(LL.LZ4_streamHC_t* context, byte* source, byte* target, int sourceLength, int targetLength) { return LL.Algorithm switch { Algorithm.X64 => LL64.LZ4_compress_HC_continue(context, source, target, sourceLength, targetLength), Algorithm.X32 => LL32.LZ4_compress_HC_continue(context, source, target, sourceLength, targetLength), _ => throw AlgorithmNotImplemented("LZ4_compress_HC_continue"), }; } } public static class Pubternal { public class FastContext : UnmanagedResources { internal unsafe LL.LZ4_stream_t* Context { get; } public unsafe FastContext() { Context = (LL.LZ4_stream_t*)Mem.AllocZero(sizeof(LL.LZ4_stream_t)); } protected unsafe override void ReleaseUnmanaged() { Mem.Free(Context); } } public unsafe static int CompressFast(FastContext context, byte* source, byte* target, int sourceLength, int targetLength, int acceleration) { return LLxx.LZ4_compress_fast_continue(context.Context, source, target, sourceLength, targetLength, acceleration); } } internal class LL32 : LL { protected static cParams_t[] clTable = new cParams_t[13] { new cParams_t(lz4hc_strat_e.lz4hc, 2u, 16u), new cParams_t(lz4hc_strat_e.lz4hc, 2u, 16u), new cParams_t(lz4hc_strat_e.lz4hc, 2u, 16u), new cParams_t(lz4hc_strat_e.lz4hc, 4u, 16u), new cParams_t(lz4hc_strat_e.lz4hc, 8u, 16u), new cParams_t(lz4hc_strat_e.lz4hc, 16u, 16u), new cParams_t(lz4hc_strat_e.lz4hc, 32u, 16u), new cParams_t(lz4hc_strat_e.lz4hc, 64u, 16u), new cParams_t(lz4hc_strat_e.lz4hc, 128u, 16u), new cParams_t(lz4hc_strat_e.lz4hc, 256u, 16u), new cParams_t(lz4hc_strat_e.lz4opt, 96u, 64u), new cParams_t(lz4hc_strat_e.lz4opt, 512u, 128u), new cParams_t(lz4hc_strat_e.lz4opt, 16384u, 4096u) }; protected const int ALGORITHM_ARCH = 4; private static readonly uint[] _DeBruijnBytePos = new uint[32] { 0u, 0u, 3u, 0u, 3u, 1u, 3u, 0u, 3u, 2u, 2u, 1u, 3u, 2u, 0u, 1u, 3u, 3u, 1u, 2u, 2u, 2u, 2u, 0u, 3u, 1u, 2u, 0u, 1u, 0u, 1u, 1u }; private unsafe static readonly uint* DeBruijnBytePos = Mem.CloneArray(_DeBruijnBytePos); [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static int LZ4_decompress_generic(byte* src, byte* dst, int srcSize, int outputSize, endCondition_directive endOnInput, earlyEnd_directive partialDecoding, dict_directive dict, byte* lowPrefix, byte* dictStart, uint dictSize) { return LZ4_decompress_generic(src, dst, srcSize, outputSize, endOnInput == endCondition_directive.endOnInputSize, partialDecoding == earlyEnd_directive.partial, dict, lowPrefix, dictStart, dictSize); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static int LZ4_decompress_generic(byte* src, byte* dst, int srcSize, int outputSize, bool endOnInput, bool partialDecoding, dict_directive dict, byte* lowPrefix, byte* dictStart, uint dictSize) { if (src == null) { return -1; } byte* ptr = src; byte* ptr2 = ptr + srcSize; byte* ptr3 = dst; byte* ptr4 = ptr3 + outputSize; byte* ptr5 = ((dictStart == null) ? null : (dictStart + dictSize)); bool flag = endOnInput; bool flag2 = flag && dictSize < 65536; byte* ptr6 = ptr2 - (endOnInput ? 14 : 8) - 2; byte* ptr7 = ptr4 - (endOnInput ? 14 : 8) - 18; if (endOnInput && outputSize == 0) { if (partialDecoding) { return 0; } if (srcSize != 1 || *ptr != 0) { return -1; } return 0; } if (!endOnInput && outputSize == 0) { if (*ptr != 0) { return -1; } return 1; } if (endOnInput && srcSize == 0) { return -1; } while (true) { uint num = *(ptr++); uint num2 = num >> 4; uint num3; byte* ptr9; byte* ptr8; if ((endOnInput ? (num2 != 15) : (num2 <= 8)) && (!endOnInput || ptr < ptr6) && ptr3 <= ptr7) { if (endOnInput) { Mem32.Copy16(ptr3, ptr); } else { Mem.Copy8(ptr3, ptr); } ptr3 += num2; ptr += num2; num2 = num & 0xFu; num3 = Mem.Peek2(ptr); ptr += 2; ptr8 = ptr3 - num3; if (num2 != 15 && num3 >= 8 && (dict == dict_directive.withPrefix64k || ptr8 >= lowPrefix)) { Mem32.Copy18(ptr3, ptr8); ptr3 += num2 + 4; continue; } } else { if (num2 == 15) { variable_length_error variable_length_error = variable_length_error.ok; num2 += LL.LZ4_readVLE(&ptr, ptr2 - 15, endOnInput, endOnInput, &variable_length_error); if (variable_length_error == variable_length_error.initial_error || (flag && ptr3 + num2 < ptr3) || (flag && ptr + num2 < ptr)) { break; } } ptr9 = ptr3 + num2; if ((endOnInput && (ptr9 > ptr4 - 12 || ptr + num2 > ptr2 - 8)) || (!endOnInput && ptr9 > ptr4 - 8)) { if (partialDecoding) { if (ptr + num2 > ptr2 - 8 && ptr + num2 != ptr2) { break; } if (ptr9 > ptr4) { ptr9 = ptr4; num2 = (uint)(ptr4 - ptr3); } } else if ((!endOnInput && ptr9 != ptr4) || (endOnInput && (ptr + num2 != ptr2 || ptr9 > ptr4))) { break; } Mem.Move(ptr3, ptr, (int)num2); ptr += num2; ptr3 += num2; if (!partialDecoding || ptr9 == ptr4 || ptr == ptr2) { goto IL_04a7; } } else { Mem32.WildCopy8(ptr3, ptr, ptr9); ptr += num2; ptr3 = ptr9; } num3 = Mem.Peek2(ptr); ptr += 2; ptr8 = ptr3 - num3; num2 = num & 0xFu; } if (num2 == 15) { variable_length_error variable_length_error2 = variable_length_error.ok; num2 += LL.LZ4_readVLE(&ptr, ptr2 - 5 + 1, endOnInput, initial_check: false, &variable_length_error2); if (variable_length_error2 != 0 || (flag && ptr3 + num2 < ptr3)) { break; } } num2 += 4; if (flag2 && ptr8 + dictSize < lowPrefix) { break; } if (dict == dict_directive.usingExtDict && ptr8 < lowPrefix) { if (ptr3 + num2 > ptr4 - 5) { if (!partialDecoding) { break; } num2 = LL.MIN(num2, (uint)(ptr4 - ptr3)); } if (num2 <= (uint)(lowPrefix - ptr8)) { Mem.Move(ptr3, ptr5 - (lowPrefix - ptr8), (int)num2); ptr3 += num2; continue; } uint num4 = (uint)(lowPrefix - ptr8); uint num5 = num2 - num4; Mem.Copy(ptr3, ptr5 - num4, (int)num4); ptr3 += num4; if (num5 > (uint)(ptr3 - lowPrefix)) { byte* ptr10 = ptr3 + num5; byte* ptr11 = lowPrefix; while (ptr3 < ptr10) { *(ptr3++) = *(ptr11++); } } else { Mem.Copy(ptr3, lowPrefix, (int)num5); ptr3 += num5; } continue; } ptr9 = ptr3 + num2; if (partialDecoding && ptr9 > ptr4 - 12) { uint num6 = LL.MIN(num2, (uint)(ptr4 - ptr3)); byte* num7 = ptr8 + num6; byte* ptr12 = ptr3 + num6; if (num7 > ptr3) { while (ptr3 < ptr12) { *(ptr3++) = *(ptr8++); } } else { Mem.Copy(ptr3, ptr8, (int)num6); } ptr3 = ptr12; if (ptr3 != ptr4) { continue; } goto IL_04a7; } if (num3 < 8) { *ptr3 = *ptr8; ptr3[1] = ptr8[1]; ptr3[2] = ptr8[2]; ptr3[3] = ptr8[3]; ptr8 += LL.inc32table[num3]; Mem.Copy4(ptr3 + 4, ptr8); ptr8 -= LL.dec64table[num3]; } else { Mem.Copy8(ptr3, ptr8); ptr8 += 8; } ptr3 += 8; if (ptr9 > ptr4 - 12) { byte* ptr13 = ptr4 - 7; if (ptr9 > ptr4 - 5) { break; } if (ptr3 < ptr13) { Mem32.WildCopy8(ptr3, ptr8, ptr13); ptr8 += ptr13 - ptr3; ptr3 = ptr13; } while (ptr3 < ptr9) { *(ptr3++) = *(ptr8++); } } else { Mem.Copy8(ptr3, ptr8); if (num2 > 16) { Mem32.WildCopy8(ptr3 + 8, ptr8 + 8, ptr9); } } ptr3 = ptr9; continue; IL_04a7: if (endOnInput) { return (int)(ptr3 - dst); } return (int)(ptr - src); } return (int)(-(ptr - src)) - 1; } public unsafe static int LZ4_decompress_safe(byte* source, byte* dest, int compressedSize, int maxDecompressedSize) { return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize, endCondition_directive.endOnInputSize, earlyEnd_directive.full, dict_directive.noDict, dest, null, 0u); } public unsafe static int LZ4_decompress_safe_withPrefix64k(byte* source, byte* dest, int compressedSize, int maxOutputSize) { return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endCondition_directive.endOnInputSize, earlyEnd_directive.full, dict_directive.withPrefix64k, dest - 65536, null, 0u); } public unsafe static int LZ4_decompress_safe_withSmallPrefix(byte* source, byte* dest, int compressedSize, int maxOutputSize, uint prefixSize) { return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endCondition_directive.endOnInputSize, earlyEnd_directive.full, dict_directive.noDict, dest - prefixSize, null, 0u); } public unsafe static int LZ4_decompress_safe_doubleDict(byte* source, byte* dest, int compressedSize, int maxOutputSize, uint prefixSize, void* dictStart, uint dictSize) { return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endCondition_directive.endOnInputSize, earlyEnd_directive.full, dict_directive.usingExtDict, dest - prefixSize, (byte*)dictStart, dictSize); } public unsafe static int LZ4_decompress_safe_forceExtDict(byte* source, byte* dest, int compressedSize, int maxOutputSize, void* dictStart, uint dictSize) { return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endCondition_directive.endOnInputSize, earlyEnd_directive.full, dict_directive.usingExtDict, dest, (byte*)dictStart, dictSize); } public unsafe static int LZ4_decompress_safe_usingDict(byte* source, byte* dest, int compressedSize, int maxOutputSize, byte* dictStart, int dictSize) { if (dictSize == 0) { return LZ4_decompress_safe(source, dest, compressedSize, maxOutputSize); } if (dictStart + dictSize == dest) { if (dictSize >= 65535) { return LZ4_decompress_safe_withPrefix64k(source, dest, compressedSize, maxOutputSize); } return LZ4_decompress_safe_withSmallPrefix(source, dest, compressedSize, maxOutputSize, (uint)dictSize); } return LZ4_decompress_safe_forceExtDict(source, dest, compressedSize, maxOutputSize, dictStart, (uint)dictSize); } public unsafe static int LZ4_decompress_safe_partial(byte* src, byte* dst, int compressedSize, int targetOutputSize, int dstCapacity) { uint outputSize = LL.MIN((uint)targetOutputSize, (uint)dstCapacity); return LZ4_decompress_generic(src, dst, compressedSize, (int)outputSize, endCondition_directive.endOnInputSize, earlyEnd_directive.partial, dict_directive.noDict, dst, null, 0u); } public unsafe static int LZ4_decompress_safe_continue(LZ4_streamDecode_t* LZ4_streamDecode, byte* source, byte* dest, int compressedSize, int maxOutputSize) { int num; if (LZ4_streamDecode->prefixSize == 0) { num = LZ4_decompress_safe(source, dest, compressedSize, maxOutputSize); if (num <= 0) { return num; } LZ4_streamDecode->prefixSize = (uint)num; LZ4_streamDecode->prefixEnd = dest + num; } else if (LZ4_streamDecode->prefixEnd == dest) { num = ((LZ4_streamDecode->prefixSize >= 65535) ? LZ4_decompress_safe_withPrefix64k(source, dest, compressedSize, maxOutputSize) : ((LZ4_streamDecode->extDictSize != 0) ? LZ4_decompress_safe_doubleDict(source, dest, compressedSize, maxOutputSize, LZ4_streamDecode->prefixSize, LZ4_streamDecode->externalDict, LZ4_streamDecode->extDictSize) : LZ4_decompress_safe_withSmallPrefix(source, dest, compressedSize, maxOutputSize, LZ4_streamDecode->prefixSize))); if (num <= 0) { return num; } LZ4_streamDecode->prefixSize += (uint)num; LZ4_streamDecode->prefixEnd += num; } else { LZ4_streamDecode->extDictSize = LZ4_streamDecode->prefixSize; LZ4_streamDecode->externalDict = LZ4_streamDecode->prefixEnd - LZ4_streamDecode->extDictSize; num = LZ4_decompress_safe_forceExtDict(source, dest, compressedSize, maxOutputSize, LZ4_streamDecode->externalDict, LZ4_streamDecode->extDictSize); if (num <= 0) { return num; } LZ4_streamDecode->prefixSize = (uint)num; LZ4_streamDecode->prefixEnd = dest + num; } return num; } [MethodImpl(MethodImplOptions.AggressiveInlining)] protected unsafe static int LZ4_compress_generic(LZ4_stream_t* cctx, byte* source, byte* dest, int inputSize, int* inputConsumed, int maxOutputSize, limitedOutput_directive outputDirective, tableType_t tableType, dict_directive dictDirective, dictIssue_directive dictIssue, int acceleration) { byte* ptr = source; uint currentOffset = cctx->currentOffset; byte* ptr2 = source - currentOffset; LZ4_stream_t* dictCtx = cctx->dictCtx; byte* ptr3 = ((dictDirective == dict_directive.usingDictCtx) ? dictCtx->dictionary : cctx->dictionary); uint num = ((dictDirective == dict_directive.usingDictCtx) ? dictCtx->dictSize : cctx->dictSize); uint num2 = ((dictDirective == dict_directive.usingDictCtx) ? (currentOffset - dictCtx->currentOffset) : 0u); bool flag = dictDirective == dict_directive.usingExtDict || dictDirective == dict_directive.usingDictCtx; uint num3 = currentOffset - num; byte* ptr4 = ptr3 + num; byte* ptr5 = source; byte* ptr6 = ptr + inputSize; byte* ptr7 = ptr6 - 12 + 1; byte* ptr8 = ptr6 - 5; byte* ptr9 = ((dictDirective == dict_directive.usingDictCtx) ? (ptr3 + num - dictCtx->currentOffset) : (ptr3 + num - currentOffset)); byte* ptr10 = dest; byte* ptr11 = ptr10 + maxOutputSize; uint num4 = 0u; if (outputDirective == limitedOutput_directive.fillOutput && maxOutputSize < 1) { return 0; } if ((uint)inputSize > 2113929216u) { return 0; } if (tableType == tableType_t.byU16 && inputSize >= 65547) { return 0; } _ = 1; byte* ptr12 = source - ((dictDirective == dict_directive.withPrefix64k) ? num : 0); if (dictDirective == dict_directive.usingDictCtx) { cctx->dictCtx = null; cctx->dictSize = (uint)inputSize; } else { cctx->dictSize += (uint)inputSize; } cctx->currentOffset += (uint)inputSize; cctx->tableType = tableType; if (inputSize >= 13) { LZ4_putPosition(ptr, cctx->hashTable, tableType, ptr2); ptr++; uint num5 = LZ4_hashPosition(ptr, tableType); while (true) { byte* ptr14; if (tableType == tableType_t.byPtr) { byte* ptr13 = ptr; int num6 = 1; int num7 = acceleration << 6; while (true) { uint h = num5; ptr = ptr13; ptr13 += num6; num6 = num7++ >> 6; if (ptr13 > ptr7) { break; } ptr14 = LL.LZ4_getPositionOnHash(h, cctx->hashTable, tableType, ptr2); num5 = LZ4_hashPosition(ptr13, tableType); LL.LZ4_putPositionOnHash(ptr, h, cctx->hashTable, tableType, ptr2); if (ptr14 + 65535 < ptr || Mem.Peek4(ptr14) != Mem.Peek4(ptr)) { continue; } goto IL_02f6; } break; } byte* ptr15 = ptr; int num8 = 1; int num9 = acceleration << 6; uint num10; uint num11; while (true) { uint h2 = num5; num10 = (uint)(ptr15 - ptr2); num11 = LL.LZ4_getIndexOnHash(h2, cctx->hashTable, tableType); ptr = ptr15; ptr15 += num8; num8 = num9++ >> 6; if (ptr15 > ptr7) { break; } switch (dictDirective) { case dict_directive.usingDictCtx: if (num11 < currentOffset) { num11 = LL.LZ4_getIndexOnHash(h2, dictCtx->hashTable, tableType_t.byU32); ptr14 = ptr9 + num11; num11 += num2; ptr12 = ptr3; } else { ptr14 = ptr2 + num11; ptr12 = source; } break; case dict_directive.usingExtDict: if (num11 < currentOffset) { ptr14 = ptr9 + num11; ptr12 = ptr3; } else { ptr14 = ptr2 + num11; ptr12 = source; } break; default: ptr14 = ptr2 + num11; break; } num5 = LZ4_hashPosition(ptr15, tableType); LL.LZ4_putIndexOnHash(num10, h2, cctx->hashTable, tableType); if ((dictIssue == dictIssue_directive.dictSmall && num11 < num3) || (tableType != tableType_t.byU16 && num11 + 65535 < num10) || Mem.Peek4(ptr14) != Mem.Peek4(ptr)) { continue; } goto IL_02eb; } break; IL_02f6: byte* ptr16 = ptr; while (ptr > ptr5 && ptr14 > ptr12 && ptr[-1] == ptr14[-1]) { ptr--; ptr14--; } uint num12 = (uint)(ptr - ptr5); byte* ptr17 = ptr10++; if (outputDirective == limitedOutput_directive.limitedOutput && ptr10 + num12 + 8 + num12 / 255 > ptr11) { return 0; } if (outputDirective == limitedOutput_directive.fillOutput && ptr10 + (num12 + 240) / 255 + num12 + 2 + 1 + 12 - 4 > ptr11) { ptr10--; break; } if (num12 >= 15) { int num13 = (int)(num12 - 15); *ptr17 = 240; while (num13 >= 255) { *(ptr10++) = byte.MaxValue; num13 -= 255; } *(ptr10++) = (byte)num13; } else { *ptr17 = (byte)(num12 << 4); } Mem32.WildCopy8(ptr10, ptr5, ptr10 + num12); ptr10 += num12; while (true) { if (outputDirective == limitedOutput_directive.fillOutput && ptr10 + 2 + 1 + 12 - 4 > ptr11) { ptr10 = ptr17; break; } if (flag) { Mem.Poke2(ptr10, (ushort)num4); ptr10 += 2; } else { Mem.Poke2(ptr10, (ushort)(ptr - ptr14)); ptr10 += 2; } uint num14; if ((dictDirective == dict_directive.usingExtDict || dictDirective == dict_directive.usingDictCtx) && ptr12 == ptr3) { byte* ptr18 = ptr + (ptr4 - ptr14); if (ptr18 > ptr8) { ptr18 = ptr8; } num14 = LZ4_count(ptr + 4, ptr14 + 4, ptr18); ptr += num14 + 4; if (ptr == ptr18) { uint num15 = LZ4_count(ptr18, source, ptr8); num14 += num15; ptr += num15; } } else { num14 = LZ4_count(ptr + 4, ptr14 + 4, ptr8); ptr += num14 + 4; } if (outputDirective != 0 && ptr10 + 6 + (num14 + 240) / 255 > ptr11) { if (outputDirective != limitedOutput_directive.fillOutput) { return 0; } uint num16 = (uint)(14 + ((int)(ptr11 - ptr10) - 1 - 5) * 255); ptr -= num14 - num16; num14 = num16; if (ptr <= ptr16) { for (byte* ptr19 = ptr; ptr19 <= ptr16; ptr19++) { LL.LZ4_clearHash(LZ4_hashPosition(ptr19, tableType), cctx->hashTable, tableType); } } } if (num14 >= 15) { byte* intPtr = ptr17; *intPtr += 15; num14 -= 15; Mem.Poke4(ptr10, uint.MaxValue); while (num14 >= 1020) { ptr10 += 4; Mem.Poke4(ptr10, uint.MaxValue); num14 -= 1020; } ptr10 += num14 / 255; *(ptr10++) = (byte)(num14 % 255); } else { byte* intPtr2 = ptr17; *intPtr2 += (byte)num14; } ptr5 = ptr; if (ptr >= ptr7) { break; } LZ4_putPosition(ptr - 2, cctx->hashTable, tableType, ptr2); if (tableType == tableType_t.byPtr) { ptr14 = LZ4_getPosition(ptr, cctx->hashTable, tableType, ptr2); LZ4_putPosition(ptr, cctx->hashTable, tableType, ptr2); if (ptr14 + 65535 >= ptr && Mem.Peek4(ptr14) == Mem.Peek4(ptr)) { ptr17 = ptr10++; *ptr17 = 0; continue; } } else { uint h3 = LZ4_hashPosition(ptr, tableType); uint num17 = (uint)(ptr - ptr2); uint num18 = LL.LZ4_getIndexOnHash(h3, cctx->hashTable, tableType); switch (dictDirective) { case dict_directive.usingDictCtx: if (num18 < currentOffset) { num18 = LL.LZ4_getIndexOnHash(h3, dictCtx->hashTable, tableType_t.byU32); ptr14 = ptr9 + num18; ptr12 = ptr3; num18 += num2; } else { ptr14 = ptr2 + num18; ptr12 = source; } break; case dict_directive.usingExtDict: if (num18 < currentOffset) { ptr14 = ptr9 + num18; ptr12 = ptr3; } else { ptr14 = ptr2 + num18; ptr12 = source; } break; default: ptr14 = ptr2 + num18; break; } LL.LZ4_putIndexOnHash(num17, h3, cctx->hashTable, tableType); if ((dictIssue != dictIssue_directive.dictSmall || num18 >= num3) && (tableType == tableType_t.byU16 || num18 + 65535 >= num17) && Mem.Peek4(ptr14) == Mem.Peek4(ptr)) { ptr17 = ptr10++; *ptr17 = 0; if (flag) { num4 = num17 - num18; } continue; } } goto IL_0703; } break; IL_0703: num5 = LZ4_hashPosition(++ptr, tableType); continue; IL_02eb: if (flag) { num4 = num10 - num11; } goto IL_02f6; } } uint num19 = (uint)(ptr6 - ptr5); if (outputDirective != 0 && ptr10 + num19 + 1 + (num19 + 255 - 15) / 255 > ptr11) { if (outputDirective != limitedOutput_directive.fillOutput) { return 0; } num19 = (uint)((int)(ptr11 - ptr10) - 1); num19 -= (num19 + 240) / 255; } if (num19 >= 15) { uint num20 = num19 - 15; *(ptr10++) = 240; while (num20 >= 255) { *(ptr10++) = byte.MaxValue; num20 -= 255; } *(ptr10++) = (byte)num20; } else { *(ptr10++) = (byte)(num19 << 4); } Mem.Copy(ptr10, ptr5, (int)num19); ptr = ptr5 + num19; ptr10 += num19; if (outputDirective == limitedOutput_directive.fillOutput) { *inputConsumed = (int)(ptr - source); } return (int)(ptr10 - dest); } public unsafe static int LZ4_compress_fast_extState(LZ4_stream_t* state, byte* source, byte* dest, int inputSize, int maxOutputSize, int acceleration) { LZ4_stream_t* cctx = LL.LZ4_initStream(state); if (acceleration < 1) { acceleration = 1; } if (maxOutputSize >= LL.LZ4_compressBound(inputSize)) { if (inputSize < 65547) { return LZ4_compress_generic(cctx, source, dest, inputSize, null, 0, limitedOutput_directive.notLimited, tableType_t.byU16, dict_directive.noDict, dictIssue_directive.noDictIssue, acceleration); } tableType_t tableType = ((sizeof(void*) < 8 && (nuint)source > (nuint)65535u) ? tableType_t.byPtr : tableType_t.byU32); return LZ4_compress_generic(cctx, source, dest, inputSize, null, 0, limitedOutput_directive.notLimited, tableType, dict_directive.noDict, dictIssue_directive.noDictIssue, acceleration); } if (inputSize < 65547) { return LZ4_compress_generic(cctx, source, dest, inputSize, null, maxOutputSize, limitedOutput_directive.limitedOutput, tableType_t.byU16, dict_directive.noDict, dictIssue_directive.noDictIssue, acceleration); } tableType_t tableType2 = ((sizeof(void*) < 8 && (nuint)source > (nuint)65535u) ? tableType_t.byPtr : tableType_t.byU32); return LZ4_compress_generic(cctx, source, dest, inputSize, null, maxOutputSize, limitedOutput_directive.limitedOutput, tableType2, dict_directive.noDict, dictIssue_directive.noDictIssue, acceleration); } public unsafe static int LZ4_compress_fast(byte* source, byte* dest, int inputSize, int maxOutputSize, int acceleration) { LZ4_stream_t lZ4_stream_t = default(LZ4_stream_t); return LZ4_compress_fast_extState(&lZ4_stream_t, source, dest, inputSize, maxOutputSize, acceleration); } public unsafe static int LZ4_compress_default(byte* src, byte* dst, int srcSize, int maxOutputSize) { return LZ4_compress_fast(src, dst, srcSize, maxOutputSize, 1); } public unsafe static int LZ4_compress_fast_continue(LZ4_stream_t* LZ4_stream, byte* source, byte* dest, int inputSize, int maxOutputSize, int acceleration) { byte* ptr = LZ4_stream->dictionary + LZ4_stream->dictSize; if (LZ4_stream->dirty) { return 0; } LZ4_renormDictT(LZ4_stream, inputSize); if (acceleration < 1) { acceleration = 1; } if (LZ4_stream->dictSize - 1 < 3 && ptr != source) { LZ4_stream->dictSize = 0u; LZ4_stream->dictionary = source; ptr = source; } byte* ptr2 = source + inputSize; if (ptr2 > LZ4_stream->dictionary && ptr2 < ptr) { LZ4_stream->dictSize = (uint)(ptr - ptr2); if (LZ4_stream->dictSize > 65536) { LZ4_stream->dictSize = 65536u; } if (LZ4_stream->dictSize < 4) { LZ4_stream->dictSize = 0u; } LZ4_stream->dictionary = ptr - LZ4_stream->dictSize; } if (ptr == source) { if (LZ4_stream->dictSize < 65536 && LZ4_stream->dictSize < LZ4_stream->currentOffset) { return LZ4_compress_generic(LZ4_stream, source, dest, inputSize, null, maxOutputSize, limitedOutput_directive.limitedOutput, tableType_t.byU32, dict_directive.withPrefix64k, dictIssue_directive.dictSmall, acceleration); } return LZ4_compress_generic(LZ4_stream, source, dest, inputSize, null, maxOutputSize, limitedOutput_directive.limitedOutput, tableType_t.byU32, dict_directive.withPrefix64k, dictIssue_directive.noDictIssue, acceleration); } int result; if (LZ4_stream->dictCtx == null) { result = ((LZ4_stream->dictSize >= 65536 || LZ4_stream->dictSize >= LZ4_stream->currentOffset) ? LZ4_compress_generic(LZ4_stream, source, dest, inputSize, null, maxOutputSize, limitedOutput_directive.limitedOutput, tableType_t.byU32, dict_directive.usingExtDict, dictIssue_directive.noDictIssue, acceleration) : LZ4_compress_generic(LZ4_stream, source, dest, inputSize, null, maxOutputSize, limitedOutput_directive.limitedOutput, tableType_t.byU32, dict_directive.usingExtDict, dictIssue_directive.dictSmall, acceleration)); } else if (inputSize > 4096) { Mem.Copy((byte*)LZ4_stream, (byte*)LZ4_stream->dictCtx, sizeof(LZ4_stream_t)); result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, null, maxOutputSize, limitedOutput_directive.limitedOutput, tableType_t.byU32, dict_directive.usingExtDict, dictIssue_directive.noDictIssue, acceleration); } else { result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, null, maxOutputSize, limitedOutput_directive.limitedOutput, tableType_t.byU32, dict_directive.usingDictCtx, dictIssue_directive.noDictIssue, acceleration); } LZ4_stream->dictionary = source; LZ4_stream->dictSize = (uint)inputSize; return result; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static uint LZ4HC_countPattern(byte* ip, byte* iEnd, uint pattern32) { byte* ptr = ip; while (ip < iEnd - 3) { uint num = Mem32.PeekW(ip) ^ pattern32; if (num == 0) { ip += 4; continue; } ip += LZ4_NbCommonBytes(num); return (uint)(ip - ptr); } uint num2 = pattern32; while (ip < iEnd && *ip == (byte)num2) { ip++; num2 >>= 8; } return (uint)(ip - ptr); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static int LZ4HC_InsertAndGetWiderMatch(LZ4_streamHC_t* hc4, byte* ip, byte* iLowLimit, byte* iHighLimit, int longest, byte** matchpos, byte** startpos, int maxNbAttempts, bool patternAnalysis, bool chainSwap, dictCtx_directive dict, HCfavor_e favorDecSpeed) { ushort* table = hc4->chainTable; uint* num = hc4->hashTable; LZ4_streamHC_t* dictCtx = hc4->dictCtx; byte* @base = hc4->@base; uint dictLimit = hc4->dictLimit; byte* ptr = @base + dictLimit; uint num2 = (uint)(ip - @base); uint num3 = ((hc4->lowLimit + 65536 > num2) ? hc4->lowLimit : (num2 - 65535)); byte* dictBase = hc4->dictBase; int num4 = (int)(ip - iLowLimit); int num5 = maxNbAttempts; uint num6 = 0u; uint num7 = Mem.Peek4(ip); repeat_state_e repeat_state_e = repeat_state_e.rep_untested; uint num8 = 0u; LL.LZ4HC_Insert(hc4, ip); uint num9 = num[LL.LZ4HC_hashPtr(ip)]; while (num9 >= num3 && num5 != 0) { int num10 = 0; num5--; if (favorDecSpeed == HCfavor_e.favorCompressionRatio || num2 - num9 >= 8) { if (num9 >= dictLimit) { byte* ptr2 = @base + num9; if (Mem.Peek2(iLowLimit + longest - 1) == Mem.Peek2(ptr2 - num4 + longest - 1) && Mem.Peek4(ptr2) == num7) { int num11 = ((num4 != 0) ? LL.LZ4HC_countBack(ip, ptr2, iLowLimit, ptr) : 0); num10 = (int)(4 + LZ4_count(ip + 4, ptr2 + 4, iHighLimit)); num10 -= num11; if (num10 > longest) { longest = num10; *matchpos = ptr2 + num11; *startpos = ip + num11; } } } else { byte* ptr3 = dictBase + num9; if (Mem.Peek4(ptr3) == num7) { byte* mMin = dictBase + hc4->lowLimit; int num12 = 0; byte* ptr4 = ip + (dictLimit - num9); if (ptr4 > iHighLimit) { ptr4 = iHighLimit; } num10 = (int)(LZ4_count(ip + 4, ptr3 + 4, ptr4) + 4); if (ip + num10 == ptr4 && ptr4 < iHighLimit) { num10 += (int)LZ4_count(ip + num10, ptr, iHighLimit); } num12 = ((num4 != 0) ? LL.LZ4HC_countBack(ip, ptr3, iLowLimit, mMin) : 0); num10 -= num12; if (num10 > longest) { longest = num10; *matchpos = @base + num9 + num12; *startpos = ip + num12; } } } } if (chainSwap && num10 == longest && (uint)((int)num9 + longest) <= num2) { int num13 = 4; uint num14 = 1u; int num15 = longest - 4 + 1; int num16 = 1; int num17 = 1 << num13; for (int i = 0; i < num15; i += num16) { uint num18 = LL.DELTANEXTU16(table, num9 + (uint)i); num16 = num17++ >> num13; if (num18 > num14) { num14 = num18; num6 = (uint)i; num17 = 1 << num13; } } if (num14 > 1) { if (num14 > num9) { break; } num9 -= num14; continue; } } uint num19 = LL.DELTANEXTU16(table, num9); if (patternAnalysis && num19 == 1 && num6 == 0) { uint num20 = num9 - 1; if (repeat_state_e == repeat_state_e.rep_untested) { if ((num7 & 0xFFFF) == num7 >> 16 && (num7 & 0xFF) == num7 >> 24) { repeat_state_e = repeat_state_e.rep_confirmed; num8 = LZ4HC_countPattern(ip + 4, iHighLimit, num7) + 4; } else { repeat_state_e = repeat_state_e.rep_not; } } if (repeat_state_e == repeat_state_e.rep_confirmed && num20 >= num3 && LL.LZ4HC_protectDictEnd(dictLimit, num20)) { bool flag = num20 < dictLimit; byte* ptr5 = (flag ? dictBase : @base) + num20; if (Mem.Peek4(ptr5) == num7) { byte* ptr6 = dictBase + hc4->lowLimit; byte* ptr7 = (flag ? (dictBase + dictLimit) : iHighLimit); uint num21 = LZ4HC_countPattern(ptr5 + 4, ptr7, num7) + 4; if (flag && ptr5 + num21 == ptr7) { uint pattern = LL.LZ4HC_rotatePattern(num21, num7); num21 += LZ4HC_countPattern(ptr, iHighLimit, pattern); } byte* iLow = (flag ? ptr6 : ptr); uint num22 = LL.LZ4HC_reverseCountPattern(ptr5, iLow, num7); if (!flag && ptr5 - num22 == ptr && hc4->lowLimit < dictLimit) { uint pattern2 = LL.LZ4HC_rotatePattern(0 - num22, num7); num22 += LL.LZ4HC_reverseCountPattern(dictBase + dictLimit, ptr6, pattern2); } num22 = num20 - LL.MAX(num20 - num22, num3); uint num23 = num22 + num21; if (num23 >= num8 && num21 <= num8) { uint num24 = num20 + num21 - num8; num9 = ((!LL.LZ4HC_protectDictEnd(dictLimit, num24)) ? dictLimit : num24); continue; } uint num25 = num20 - num22; if (!LL.LZ4HC_protectDictEnd(dictLimit, num25)) { num9 = dictLimit; continue; } num9 = num25; if (num4 != 0) { continue; } uint num26 = LL.MIN(num23, num8); if ((uint)longest < num26) { if ((uint)((int)(ip - @base) - (int)num9) > 65535u) { break; } longest = (int)num26; *matchpos = @base + num9; *startpos = ip; } uint num27 = LL.DELTANEXTU16(table, num9); if (num27 > num9) { break; } num9 -= num27; continue; } } } num9 -= LL.DELTANEXTU16(table, num9 + num6); } if (dict == dictCtx_directive.usingDictCtxHc && num5 != 0 && num2 - num3 < 65535) { uint num28 = (uint)(dictCtx->end - dictCtx->@base); uint num29 = dictCtx->hashTable[LL.LZ4HC_hashPtr(ip)]; num9 = num29 + num3 - num28; while (num2 - num9 <= 65535 && num5-- != 0) { byte* ptr8 = dictCtx->@base + num29; if (Mem.Peek4(ptr8) == num7) { int num30 = 0; byte* ptr9 = ip + (num28 - num29); if (ptr9 > iHighLimit) { ptr9 = iHighLimit; } int num31 = (int)(LZ4_count(ip + 4, ptr8 + 4, ptr9) + 4); num30 = ((num4 != 0) ? LL.LZ4HC_countBack(ip, ptr8, iLowLimit, dictCtx->@base + dictCtx->dictLimit) : 0); num31 -= num30; if (num31 > longest) { longest = num31; *matchpos = @base + num9 + num30; *startpos = ip + num30; } } uint num32 = LL.DELTANEXTU16(dictCtx->chainTable, num29); num29 -= num32; num9 -= num32; } } return longest; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static int LZ4HC_InsertAndFindBestMatch(LZ4_streamHC_t* hc4, byte* ip, byte* iLimit, byte** matchpos, int maxNbAttempts, bool patternAnalysis, dictCtx_directive dict) { byte* ptr = ip; return LZ4HC_InsertAndGetWiderMatch(hc4, ip, ip, iLimit, 3, matchpos, &ptr, maxNbAttempts, patternAnalysis, chainSwap: false, dict, HCfavor_e.favorCompressionRatio); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static LZ4HC_match_t LZ4HC_FindLongerMatch(LZ4_streamHC_t* ctx, byte* ip, byte* iHighLimit, int minLen, int nbSearches, dictCtx_directive dict, HCfavor_e favorDecSpeed) { LZ4HC_match_t result = default(LZ4HC_match_t); result.len = 0; result.off = 0; byte* ptr = null; int num = LZ4HC_InsertAndGetWiderMatch(ctx, ip, ip, iHighLimit, minLen, &ptr, &ip, nbSearches, patternAnalysis: true, chainSwap: true, dict, favorDecSpeed); if (num <= minLen) { return result; } if (favorDecSpeed != 0 && num > 18 && num <= 36) { num = 18; } result.len = num; result.off = (int)(ip - ptr); return result; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static int LZ4HC_encodeSequence(byte** ip, byte** op, byte** anchor, int matchLength, byte* match, limitedOutput_directive limit, byte* oend) { byte* ptr = (*op)++; uint num = (uint)(*ip - *anchor); if (limit != 0 && *op + num / 255 + num + 8 > oend) { return 1; } if (num >= 15) { uint num2 = num - 15; *ptr = 240; while (num2 >= 255) { *((*op)++) = byte.MaxValue; num2 -= 255; } *((*op)++) = (byte)num2; } else { *ptr = (byte)(num << 4); } Mem32.WildCopy8(*op, *anchor, *op + num); *op += num; Mem.Poke2(*op, (ushort)(*ip - match)); *op += 2; num = (uint)(matchLength - 4); if (limit != 0 && *op + num / 255 + 6 > oend) { return 1; } if (num >= 15) { *ptr += 15; for (num -= 15; num >= 510; num -= 510) { *((*op)++) = byte.MaxValue; *((*op)++) = byte.MaxValue; } if (num >= 255) { num -= 255; *((*op)++) = byte.MaxValue; } *((*op)++) = (byte)num; } else { *ptr += (byte)num; } *ip += matchLength; *anchor = *ip; return 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static int LZ4HC_compress_hashChain(LZ4_streamHC_t* ctx, byte* source, byte* dest, int* srcSizePtr, int maxOutputSize, int maxNbAttempts, limitedOutput_directive limit, dictCtx_directive dict) { int num = *srcSizePtr; bool patternAnalysis = maxNbAttempts > 128; byte* ptr = source; byte* ptr2 = ptr; byte* ptr3 = ptr + num; byte* ptr4 = ptr3 - 12; byte* ptr5 = ptr3 - 5; byte* ptr6 = dest; byte* ptr7 = dest; byte* ptr8 = ptr7 + maxOutputSize; byte* ptr9 = null; byte* ptr10 = null; byte* ptr11 = null; byte* ptr12 = null; byte* ptr13 = null; *srcSizePtr = 0; if (limit == limitedOutput_directive.fillOutput) { ptr8 -= 5; } if (num >= 13) { while (ptr <= ptr4) { int num2 = LZ4HC_InsertAndFindBestMatch(ctx, ptr, ptr5, &ptr9, maxNbAttempts, patternAnalysis, dict); if (num2 < 4) { ptr++; continue; } byte* ptr14 = ptr; byte* ptr15 = ptr9; int num3 = num2; while (true) { int num4 = ((ptr + num2 > ptr4) ? num2 : LZ4HC_InsertAndGetWiderMatch(ctx, ptr + num2 - 2, ptr, ptr5, num2, &ptr11, &ptr10, maxNbAttempts, patternAnalysis, chainSwap: false, dict, HCfavor_e.favorCompressionRatio)); int num7; if (num4 == num2) { ptr6 = ptr7; if (LZ4HC_encodeSequence(&ptr, &ptr7, &ptr2, num2, ptr9, limit, ptr8) == 0) { break; } } else { if (ptr14 < ptr && ptr10 < ptr + num3) { ptr = ptr14; ptr9 = ptr15; num2 = num3; } if (ptr10 - ptr < 3) { num2 = num4; ptr = ptr10; ptr9 = ptr11; continue; } while (true) { if (ptr10 - ptr < 18) { int num5 = num2; if (num5 > 18) { num5 = 18; } if (ptr + num5 > ptr10 + num4 - 4) { num5 = (int)(ptr10 - ptr) + num4 - 4; } int num6 = num5 - (int)(ptr10 - ptr); if (num6 > 0) { ptr10 += num6; ptr11 += num6; num4 -= num6; } } num7 = ((ptr10 + num4 > ptr4) ? num4 : LZ4HC_InsertAndGetWiderMatch(ctx, ptr10 + num4 - 3, ptr10, ptr5, num4, &ptr13, &ptr12, maxNbAttempts, patternAnalysis, chainSwap: false, dict, HCfavor_e.favorCompressionRatio)); if (num7 == num4) { break; } if (ptr12 < ptr + num2 + 3) { if (ptr12 < ptr + num2) { ptr10 = ptr12; ptr11 = ptr13; num4 = num7; continue; } goto IL_0217; } if (ptr10 < ptr + num2) { if (ptr10 - ptr < 18) { if (num2 > 18) { num2 = 18; } if (ptr + num2 > ptr10 + num4 - 4) { num2 = (int)(ptr10 - ptr) + num4 - 4; } int num8 = num2 - (int)(ptr10 - ptr); if (num8 > 0) { ptr10 += num8; ptr11 += num8; num4 -= num8; } } else { num2 = (int)(ptr10 - ptr); } } ptr6 = ptr7; if (LZ4HC_encodeSequence(&ptr, &ptr7, &ptr2, num2, ptr9, limit, ptr8) == 0) { ptr = ptr10; ptr9 = ptr11; num2 = num4; ptr10 = ptr12; ptr11 = ptr13; num4 = num7; continue; } goto IL_043b; } if (ptr10 < ptr + num2) { num2 = (int)(ptr10 - ptr); } ptr6 = ptr7; if (LZ4HC_encodeSequence(&ptr, &ptr7, &ptr2, num2, ptr9, limit, ptr8) == 0) { ptr = ptr10; ptr6 = ptr7; if (LZ4HC_encodeSequence(&ptr, &ptr7, &ptr2, num4, ptr11, limit, ptr8) == 0) { break; } } } goto IL_043b; IL_043b: if (limit != limitedOutput_directive.fillOutput) { return 0; } goto IL_0440; IL_0217: if (ptr10 < ptr + num2) { int num9 = (int)(ptr + num2 - ptr10); ptr10 += num9; ptr11 += num9; num4 -= num9; if (num4 < 4) { ptr10 = ptr12; ptr11 = ptr13; num4 = num7; } } ptr6 = ptr7; if (LZ4HC_encodeSequence(&ptr, &ptr7, &ptr2, num2, ptr9, limit, ptr8) == 0) { ptr = ptr12; ptr9 = ptr13; num2 = num7; ptr14 = ptr10; ptr15 = ptr11; num3 = num4; continue; } goto IL_043b; } continue; IL_0440: ptr7 = ptr6; break; } } uint num10 = (uint)(ptr3 - ptr2); uint num11 = (num10 + 255 - 15) / 255; uint num12 = 1 + num11 + num10; if (limit == limitedOutput_directive.fillOutput) { ptr8 += 5; } if (limit != 0 && ptr7 + num12 > ptr8) { if (limit == limitedOutput_directive.limitedOutput) { return 0; } num10 = (uint)((int)(ptr8 - ptr7) - 1); num11 = (num10 + 255 - 15) / 255; num10 -= num11; } ptr = ptr2 + num10; if (num10 >= 15) { uint num13 = num10 - 15; *(ptr7++) = 240; while (num13 >= 255) { *(ptr7++) = byte.MaxValue; num13 -= 255; } *(ptr7++) = (byte)num13; } else { *(ptr7++) = (byte)(num10 << 4); } Mem.Copy(ptr7, ptr2, (int)num10); ptr7 += num10; *srcSizePtr = (int)(ptr - source); return (int)(ptr7 - dest); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static int LZ4HC_compress_optimal(LZ4_streamHC_t* ctx, byte* source, byte* dst, int* srcSizePtr, int dstCapacity, int nbSearches, uint sufficient_len, limitedOutput_directive limit, bool fullUpdate, dictCtx_directive dict, HCfavor_e favorDecSpeed) { LZ4HC_optimal_t* ptr = stackalloc LZ4HC_optimal_t[4099]; byte* ptr2 = source; byte* ptr3 = ptr2; byte* ptr4 = ptr2 + *srcSizePtr; byte* ptr5 = ptr4 - 12; byte* iHighLimit = ptr4 - 5; byte* ptr6 = dst; byte* ptr7 = dst; byte* ptr8 = ptr6 + dstCapacity; *srcSizePtr = 0; if (limit == limitedOutput_directive.fillOutput) { ptr8 -= 5; } if (sufficient_len >= 4096) { sufficient_len = 4095u; } while (true) { if (ptr2 > ptr5) { goto IL_06aa; } int num = (int)(ptr2 - ptr3); int num2 = 0; LZ4HC_match_t lZ4HC_match_t = LZ4HC_FindLongerMatch(ctx, ptr2, iHighLimit, 3, nbSearches, dict, favorDecSpeed); if (lZ4HC_match_t.len == 0) { ptr2++; continue; } if ((uint)lZ4HC_match_t.len > sufficient_len) { int len = lZ4HC_match_t.len; byte* match = ptr2 - lZ4HC_match_t.off; ptr7 = ptr6; if (LZ4HC_encodeSequence(&ptr2, &ptr6, &ptr3, len, match, limit, ptr8) == 0) { continue; } goto IL_0796; } for (int i = 0; i < 4; i++) { int price = LL.LZ4HC_literalsPrice(num + i); ptr[i].mlen = 1; ptr[i].off = 0; ptr[i].litlen = num + i; ptr[i].price = price; } int j = 4; int len2 = lZ4HC_match_t.len; int off = lZ4HC_match_t.off; for (; j <= len2; j++) { int price2 = LL.LZ4HC_sequencePrice(num, j); ptr[j].mlen = j; ptr[j].off = off; ptr[j].litlen = num; ptr[j].price = price2; } num2 = lZ4HC_match_t.len; for (int k = 1; k <= 3; k++) { ptr[num2 + k].mlen = 1; ptr[num2 + k].off = 0; ptr[num2 + k].litlen = k; ptr[num2 + k].price = ptr[num2].price + LL.LZ4HC_literalsPrice(k); } int num3 = 1; int num4; int off2; while (