You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
159 lines
6.4 KiB
159 lines
6.4 KiB
4 years ago
|
#region license
|
||
|
|
||
|
/*
|
||
|
Copyright (c) 2013, Milosz Krajewski
|
||
|
All rights reserved.
|
||
|
|
||
|
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||
|
that the following conditions are met:
|
||
|
|
||
|
* Redistributions of source code must retain the above copyright notice, this list of conditions
|
||
|
and the following disclaimer.
|
||
|
|
||
|
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions
|
||
|
and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||
|
|
||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||
|
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||
|
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
|
*/
|
||
|
|
||
|
#endregion
|
||
|
|
||
|
using System;
|
||
|
|
||
|
// ReSharper disable InconsistentNaming
|
||
|
|
||
|
namespace MessagePack.LZ4
|
||
|
{
|
||
|
public static partial class LZ4Codec
|
||
|
{
|
||
|
#region configuration
|
||
|
|
||
|
/// <summary>
|
||
|
/// Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)
|
||
|
/// Increasing memory usage improves compression ratio
|
||
|
/// Reduced memory usage can improve speed, due to cache effect
|
||
|
/// Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache
|
||
|
/// </summary>
|
||
|
private const int MEMORY_USAGE = 12; // modified use 12.
|
||
|
|
||
|
/// <summary>
|
||
|
/// Decreasing this value will make the algorithm skip faster data segments considered "incompressible"
|
||
|
/// This may decrease compression ratio dramatically, but will be faster on incompressible data
|
||
|
/// Increasing this value will make the algorithm search more before declaring a segment "incompressible"
|
||
|
/// This could improve compression a bit, but will be slower on incompressible data
|
||
|
/// The default value (6) is recommended
|
||
|
/// </summary>
|
||
|
private const int NOTCOMPRESSIBLE_DETECTIONLEVEL = 6;
|
||
|
|
||
|
#endregion
|
||
|
|
||
|
#region consts
|
||
|
|
||
|
private const int MINMATCH = 4;
|
||
|
|
||
|
#pragma warning disable 162, 429
|
||
|
// ReSharper disable once UnreachableCode
|
||
|
private const int SKIPSTRENGTH =
|
||
|
NOTCOMPRESSIBLE_DETECTIONLEVEL > 2
|
||
|
? NOTCOMPRESSIBLE_DETECTIONLEVEL
|
||
|
: 2;
|
||
|
#pragma warning restore 162, 429
|
||
|
|
||
|
private const int COPYLENGTH = 8;
|
||
|
private const int LASTLITERALS = 5;
|
||
|
private const int MFLIMIT = COPYLENGTH + MINMATCH;
|
||
|
private const int MINLENGTH = MFLIMIT + 1;
|
||
|
private const int MAXD_LOG = 16;
|
||
|
private const int MAXD = 1 << MAXD_LOG;
|
||
|
private const int MAXD_MASK = MAXD - 1;
|
||
|
private const int MAX_DISTANCE = (1 << MAXD_LOG) - 1;
|
||
|
private const int ML_BITS = 4;
|
||
|
private const int ML_MASK = (1 << ML_BITS) - 1;
|
||
|
private const int RUN_BITS = 8 - ML_BITS;
|
||
|
private const int RUN_MASK = (1 << RUN_BITS) - 1;
|
||
|
private const int STEPSIZE_64 = 8;
|
||
|
private const int STEPSIZE_32 = 4;
|
||
|
|
||
|
private const int LZ4_64KLIMIT = (1 << 16) + (MFLIMIT - 1);
|
||
|
|
||
|
private const int HASH_LOG = MEMORY_USAGE - 2;
|
||
|
private const int HASH_TABLESIZE = 1 << HASH_LOG;
|
||
|
private const int HASH_ADJUST = (MINMATCH * 8) - HASH_LOG;
|
||
|
|
||
|
private const int HASH64K_LOG = HASH_LOG + 1;
|
||
|
private const int HASH64K_TABLESIZE = 1 << HASH64K_LOG;
|
||
|
private const int HASH64K_ADJUST = (MINMATCH * 8) - HASH64K_LOG;
|
||
|
|
||
|
private const int HASHHC_LOG = MAXD_LOG - 1;
|
||
|
private const int HASHHC_TABLESIZE = 1 << HASHHC_LOG;
|
||
|
private const int HASHHC_ADJUST = (MINMATCH * 8) - HASHHC_LOG;
|
||
|
//private const int HASHHC_MASK = HASHHC_TABLESIZE - 1;
|
||
|
|
||
|
private static readonly int[] DECODER_TABLE_32 = { 0, 3, 2, 3, 0, 0, 0, 0 };
|
||
|
private static readonly int[] DECODER_TABLE_64 = { 0, 0, 0, -1, 0, 1, 2, 3 };
|
||
|
|
||
|
private static readonly int[] DEBRUIJN_TABLE_32 = {
|
||
|
0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1,
|
||
|
3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1
|
||
|
};
|
||
|
|
||
|
private static readonly int[] DEBRUIJN_TABLE_64 = {
|
||
|
0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7,
|
||
|
0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7,
|
||
|
7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6,
|
||
|
7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7
|
||
|
};
|
||
|
|
||
|
private const int MAX_NB_ATTEMPTS = 256;
|
||
|
private const int OPTIMAL_ML = (ML_MASK - 1) + MINMATCH;
|
||
|
|
||
|
private const int BLOCK_COPY_LIMIT = 16;
|
||
|
|
||
|
#endregion
|
||
|
|
||
|
#region public interface (common)
|
||
|
|
||
|
/// <summary>Gets maximum the length of the output.</summary>
|
||
|
/// <param name="inputLength">Length of the input.</param>
|
||
|
/// <returns>Maximum number of bytes needed for compressed buffer.</returns>
|
||
|
public static int MaximumOutputLength(int inputLength)
|
||
|
{
|
||
|
return inputLength + (inputLength / 255) + 16;
|
||
|
}
|
||
|
|
||
|
#endregion
|
||
|
|
||
|
#region internal interface (common)
|
||
|
|
||
|
internal static void CheckArguments(
|
||
|
byte[] input, int inputOffset, int inputLength,
|
||
|
byte[] output, int outputOffset, int outputLength)
|
||
|
{
|
||
|
if (inputLength == 0)
|
||
|
{
|
||
|
outputLength = 0;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (input == null) throw new ArgumentNullException("input");
|
||
|
if ((uint)inputOffset > (uint)input.Length) throw new ArgumentOutOfRangeException("inputOffset");
|
||
|
if ((uint)inputLength > (uint)input.Length - (uint)inputOffset) throw new ArgumentOutOfRangeException("inputLength");
|
||
|
|
||
|
if (output == null) throw new ArgumentNullException("output");
|
||
|
if ((uint)outputOffset > (uint)output.Length) throw new ArgumentOutOfRangeException("outputOffset");
|
||
|
if ((uint)outputLength > (uint)output.Length - (uint)outputOffset) throw new ArgumentOutOfRangeException("outputLength");
|
||
|
}
|
||
|
|
||
|
#endregion
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// ReSharper restore InconsistentNaming
|