mirror of
https://github.com/chylex/Brotli-Builder.git
synced 2025-05-12 23:34:04 +02:00
Rename DistanceCodeZeroStrategy & repurpose old name for command builder
This commit is contained in:
parent
661004e67f
commit
9c4515d9e7
BrotliLib/Brotli
Components/Data
Encode/Build
Utils
UnitTests/Brotli
@ -81,7 +81,7 @@ namespace BrotliLib.Brotli.Components.Data{
|
||||
/// <summary>
|
||||
/// Initializes the code with the concrete insert and copy codes, and the flag which determines whether to use an implied distance code zero.
|
||||
/// </summary>
|
||||
public InsertCopyLengthCode(int insertCode, int copyCode, DistanceCodeZeroStrategy dczStrategy){
|
||||
public InsertCopyLengthCode(int insertCode, int copyCode, ImplicitDistanceCodeZero implicitDCZ){
|
||||
if (insertCode < 0 || insertCode > 23){
|
||||
throw new ArgumentOutOfRangeException(nameof(insertCode), "Insert code must be in the range [0; 23].");
|
||||
}
|
||||
@ -90,7 +90,7 @@ namespace BrotliLib.Brotli.Components.Data{
|
||||
throw new ArgumentOutOfRangeException(nameof(copyCode), "Copy code must be in the range [0; 23].");
|
||||
}
|
||||
|
||||
bool useDistanceCodeZero = dczStrategy.Determine(insertCode, copyCode);
|
||||
bool useDistanceCodeZero = implicitDCZ.Decide(insertCode, copyCode);
|
||||
|
||||
int cell = DetermineCellIndex(insertCode, copyCode, useDistanceCodeZero);
|
||||
|
||||
|
@ -31,7 +31,7 @@ namespace BrotliLib.Brotli.Components.Data{
|
||||
}
|
||||
|
||||
public static bool CanUseImplicitDCZ(int insertLength, int copyLength){
|
||||
return new InsertCopyLengths(insertLength, copyLength).MakeCode(DistanceCodeZeroStrategy.PreferEnabled).UseDistanceCodeZero;
|
||||
return new InsertCopyLengths(insertLength, copyLength).MakeCode(ImplicitDistanceCodeZero.PreferEnabled).UseDistanceCodeZero;
|
||||
}
|
||||
|
||||
// Insert code tables
|
||||
@ -96,14 +96,14 @@ namespace BrotliLib.Brotli.Components.Data{
|
||||
/// <summary>
|
||||
/// Constructs an <see cref="InsertCopyLengthCode"/> that can encode the stored lengths, and can therefore be used as context in the <see cref="Serialize"/>.
|
||||
/// </summary>
|
||||
public InsertCopyLengthCode MakeCode(DistanceCodeZeroStrategy dczStrategy){
|
||||
public InsertCopyLengthCode MakeCode(ImplicitDistanceCodeZero implicitDCZ){
|
||||
int insertLength = InsertLength;
|
||||
int copyLength = CopyLength;
|
||||
|
||||
int insertCode = CollectionHelper.FindRangeIndex(InsertCodeRanges, insertLength);
|
||||
int copyCode = CollectionHelper.FindRangeIndex(CopyCodeRanges, copyLength);
|
||||
|
||||
return new InsertCopyLengthCode(insertCode, copyCode, dczStrategy);
|
||||
return new InsertCopyLengthCode(insertCode, copyCode, implicitDCZ);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -99,18 +99,9 @@ namespace BrotliLib.Brotli.Encode.Build{
|
||||
return AddInsertCopy(new InsertCopyCommand(literals, copyLength, copyDistance));
|
||||
}
|
||||
|
||||
public CompressedMetaBlockBuilder AddInsertCopy(IList<Literal> literals, int copyLength, int copyDistance, DistanceCodeZeroStrategy dczStrategy = DistanceCodeZeroStrategy.PreferEnabled){
|
||||
public CompressedMetaBlockBuilder AddInsertCopy(IList<Literal> literals, int copyLength, int copyDistance, DistanceCodeZeroStrategy dczStrategy = DistanceCodeZeroStrategy.PreferImplicit){
|
||||
if (copyDistance == LastDistance){
|
||||
switch(dczStrategy){
|
||||
case DistanceCodeZeroStrategy.ForceEnabled:
|
||||
return AddInsertCopy(literals, copyLength, DistanceInfo.ImplicitCodeZero);
|
||||
|
||||
case DistanceCodeZeroStrategy.PreferEnabled:
|
||||
return AddInsertCopy(literals, copyLength, InsertCopyLengths.CanUseImplicitDCZ(literals.Count, copyLength) ? DistanceInfo.ImplicitCodeZero : DistanceInfo.ExplicitCodeZero);
|
||||
|
||||
case DistanceCodeZeroStrategy.Disable:
|
||||
break; // uses the copy distance verbatim
|
||||
}
|
||||
return AddInsertCopy(literals, copyLength, dczStrategy.Decide(literals.Count, copyLength, copyDistance));
|
||||
}
|
||||
|
||||
return AddInsertCopy(new InsertCopyCommand(literals, copyLength, copyDistance));
|
||||
@ -120,10 +111,10 @@ namespace BrotliLib.Brotli.Encode.Build{
|
||||
var startDistance = 1 + Math.Min(intermediateState.Parameters.WindowSize.Bytes, intermediateState.OutputSize + literals.Count);
|
||||
var entryDistance = dictionaryEntry.Packed + startDistance;
|
||||
|
||||
return AddInsertCopy(literals, dictionaryEntry.CopyLength, entryDistance, DistanceCodeZeroStrategy.Disable);
|
||||
return AddInsertCopy(literals, dictionaryEntry.CopyLength, entryDistance, DistanceCodeZeroStrategy.Avoid);
|
||||
}
|
||||
|
||||
public CompressedMetaBlockBuilder AddCopy(int copyLength, int copyDistance, DistanceCodeZeroStrategy dczStrategy = DistanceCodeZeroStrategy.PreferEnabled){
|
||||
public CompressedMetaBlockBuilder AddCopy(int copyLength, int copyDistance, DistanceCodeZeroStrategy dczStrategy = DistanceCodeZeroStrategy.PreferImplicit){
|
||||
return AddInsertCopy(Array.Empty<Literal>(), copyLength, copyDistance, dczStrategy);
|
||||
}
|
||||
|
||||
@ -201,10 +192,10 @@ namespace BrotliLib.Brotli.Encode.Build{
|
||||
throw new InvalidOperationException("Insert© command that ends after literals must be the last.");
|
||||
}
|
||||
|
||||
icLengthCode = icLengthValues.MakeCode(DistanceCodeZeroStrategy.PreferEnabled);
|
||||
icLengthCode = icLengthValues.MakeCode(ImplicitDistanceCodeZero.PreferEnabled);
|
||||
|
||||
if (icLengthCode.UseDistanceCodeZero){
|
||||
var alternativeCode = icLengthValues.MakeCode(DistanceCodeZeroStrategy.Disable);
|
||||
var alternativeCode = icLengthValues.MakeCode(ImplicitDistanceCodeZero.Disable);
|
||||
|
||||
if (icFreq[alternativeCode] > icFreq[icLengthCode]){
|
||||
icLengthCode = alternativeCode; // if the first code uses DCZ, try a non-DCZ code and pick whichever one was used more often
|
||||
@ -215,7 +206,7 @@ namespace BrotliLib.Brotli.Encode.Build{
|
||||
var distanceCodes = icCommand.CopyDistance.MakeCode(DistanceParameters, state);
|
||||
|
||||
if (distanceCodes == null){
|
||||
icLengthCode = icLengthValues.MakeCode(DistanceCodeZeroStrategy.ForceEnabled);
|
||||
icLengthCode = icLengthValues.MakeCode(ImplicitDistanceCodeZero.ForceEnabled);
|
||||
}
|
||||
else{
|
||||
int blockID = blockTrackers[Category.Distance].SimulateCommand();
|
||||
@ -237,7 +228,7 @@ namespace BrotliLib.Brotli.Encode.Build{
|
||||
}
|
||||
|
||||
codeList.Add(distanceCode);
|
||||
icLengthCode = icLengthValues.MakeCode(DistanceCodeZeroStrategy.Disable);
|
||||
icLengthCode = icLengthValues.MakeCode(ImplicitDistanceCodeZero.Disable);
|
||||
}
|
||||
|
||||
state.OutputCopy(icCommand.CopyLength, icCommand.CopyDistance);
|
||||
|
@ -3,44 +3,40 @@ using BrotliLib.Brotli.Components.Data;
|
||||
|
||||
namespace BrotliLib.Brotli.Utils{
|
||||
/// <summary>
|
||||
/// Determines how to set <see cref="InsertCopyLengthCode.UseDistanceCodeZero"/> during construction.
|
||||
/// Determines how to pick <see cref="DistanceInfo"/> for an insert&copy command whose distance can be encoded using <see cref="DistanceCode.Zero"/>.
|
||||
/// </summary>
|
||||
public enum DistanceCodeZeroStrategy{
|
||||
/// <summary>
|
||||
/// Always sets <see cref="InsertCopyLengthCode.UseDistanceCodeZero"/> to <c>false</c>.
|
||||
/// If possible, uses an implicit code zero encoded in <see cref="InsertCopyLengthCode.UseDistanceCodeZero"/>.
|
||||
/// Otherwise, throws <see cref="InvalidOperationException"/>.
|
||||
/// </summary>
|
||||
Disable,
|
||||
ForceImplicit,
|
||||
|
||||
/// <summary>
|
||||
/// Sets <see cref="InsertCopyLengthCode.UseDistanceCodeZero"/> to <c>true</c> if possible with the provided insert & copy codes, <c>false</c> otherwise.
|
||||
/// If possible, uses an implicit code zero encoded in <see cref="InsertCopyLengthCode.UseDistanceCodeZero"/>.
|
||||
/// Otherwise, uses an explicit <see cref="DistanceCode.Zero"/>.
|
||||
/// </summary>
|
||||
PreferEnabled,
|
||||
PreferImplicit,
|
||||
|
||||
/// <summary>
|
||||
/// Sets <see cref="InsertCopyLengthCode.UseDistanceCodeZero"/> to <c>true</c> if possible with the provided insert & copy codes, throws <see cref="ArgumentOutOfRangeException"/> otherwise.
|
||||
/// Uses an explicit <see cref="DistanceCode.Zero"/>.
|
||||
/// </summary>
|
||||
ForceEnabled
|
||||
Explicit,
|
||||
|
||||
/// <summary>
|
||||
/// Uses a non-zero <see cref="DistanceCode"/>.
|
||||
/// </summary>
|
||||
Avoid
|
||||
}
|
||||
|
||||
internal static class DistanceCodeZeroStrategies{
|
||||
public static bool Determine(this DistanceCodeZeroStrategy strategy, int insertCode, int copyCode){
|
||||
|
||||
internal static class DistanceCodeZeroStrategyExtensions{
|
||||
public static DistanceInfo Decide(this DistanceCodeZeroStrategy strategy, int insertLength, int copyLength, int copyDistance){
|
||||
return strategy switch{
|
||||
DistanceCodeZeroStrategy.Disable
|
||||
=> false,
|
||||
|
||||
DistanceCodeZeroStrategy.PreferEnabled
|
||||
=> insertCode <= 7 && copyCode <= 15,
|
||||
|
||||
DistanceCodeZeroStrategy.ForceEnabled when insertCode > 7
|
||||
=> throw new ArgumentOutOfRangeException(nameof(insertCode), "Insert code must be in the range [0; 7] when using implied distance code zero."),
|
||||
|
||||
DistanceCodeZeroStrategy.ForceEnabled when copyCode > 15
|
||||
=> throw new ArgumentOutOfRangeException(nameof(copyCode), "Copy code must be in the range [0; 15] when using implied distance code zero."),
|
||||
|
||||
DistanceCodeZeroStrategy.ForceEnabled
|
||||
=> true,
|
||||
|
||||
_ => throw new InvalidOperationException("Invalid distance code zero strategy: " + strategy),
|
||||
DistanceCodeZeroStrategy.ForceImplicit => DistanceInfo.ImplicitCodeZero,
|
||||
DistanceCodeZeroStrategy.PreferImplicit => InsertCopyLengths.CanUseImplicitDCZ(insertLength, copyLength) ? DistanceInfo.ImplicitCodeZero : DistanceInfo.ExplicitCodeZero,
|
||||
DistanceCodeZeroStrategy.Explicit => DistanceInfo.ExplicitCodeZero,
|
||||
DistanceCodeZeroStrategy.Avoid => (DistanceInfo)copyDistance,
|
||||
_ => throw new InvalidOperationException("Invalid distance code zero strategy: " + strategy),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
47
BrotliLib/Brotli/Utils/ImplicitDistanceCodeZero.cs
Normal file
47
BrotliLib/Brotli/Utils/ImplicitDistanceCodeZero.cs
Normal file
@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using BrotliLib.Brotli.Components.Data;
|
||||
|
||||
namespace BrotliLib.Brotli.Utils{
|
||||
/// <summary>
|
||||
/// Determines how to set <see cref="InsertCopyLengthCode.UseDistanceCodeZero"/> during construction.
|
||||
/// </summary>
|
||||
public enum ImplicitDistanceCodeZero{
|
||||
/// <summary>
|
||||
/// Always sets <see cref="InsertCopyLengthCode.UseDistanceCodeZero"/> to <c>false</c>.
|
||||
/// </summary>
|
||||
Disable,
|
||||
|
||||
/// <summary>
|
||||
/// Sets <see cref="InsertCopyLengthCode.UseDistanceCodeZero"/> to <c>true</c> if possible with the provided insert & copy codes, <c>false</c> otherwise.
|
||||
/// </summary>
|
||||
PreferEnabled,
|
||||
|
||||
/// <summary>
|
||||
/// Sets <see cref="InsertCopyLengthCode.UseDistanceCodeZero"/> to <c>true</c> if possible with the provided insert & copy codes, throws <see cref="ArgumentOutOfRangeException"/> otherwise.
|
||||
/// </summary>
|
||||
ForceEnabled
|
||||
}
|
||||
|
||||
internal static class ImplicitDistanceCodeZeroExtensions{
|
||||
public static bool Decide(this ImplicitDistanceCodeZero strategy, int insertCode, int copyCode){
|
||||
return strategy switch{
|
||||
ImplicitDistanceCodeZero.Disable
|
||||
=> false,
|
||||
|
||||
ImplicitDistanceCodeZero.PreferEnabled
|
||||
=> insertCode <= 7 && copyCode <= 15,
|
||||
|
||||
ImplicitDistanceCodeZero.ForceEnabled when insertCode > 7
|
||||
=> throw new ArgumentOutOfRangeException(nameof(insertCode), "Insert code must be in the range [0; 7] when using implied distance code zero."),
|
||||
|
||||
ImplicitDistanceCodeZero.ForceEnabled when copyCode > 15
|
||||
=> throw new ArgumentOutOfRangeException(nameof(copyCode), "Copy code must be in the range [0; 15] when using implied distance code zero."),
|
||||
|
||||
ImplicitDistanceCodeZero.ForceEnabled
|
||||
=> true,
|
||||
|
||||
_ => throw new InvalidOperationException("Invalid implicit distance code zero strategy: " + strategy),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -272,8 +272,8 @@ module InsertCopyLengths =
|
||||
for original in icCodeRange do
|
||||
let dczStrategy =
|
||||
match original.UseDistanceCodeZero with
|
||||
| true -> DistanceCodeZeroStrategy.ForceEnabled
|
||||
| false -> DistanceCodeZeroStrategy.Disable
|
||||
| true -> ImplicitDistanceCodeZero.ForceEnabled
|
||||
| false -> ImplicitDistanceCodeZero.Disable
|
||||
|
||||
let reconstructed = InsertCopyLengthCode(original.InsertCode, original.CopyCode, dczStrategy)
|
||||
Assert.Equal(original.CompactedCode, reconstructed.CompactedCode)
|
||||
|
Loading…
Reference in New Issue
Block a user