1
0
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:
chylex 2020-03-15 08:46:14 +01:00
parent 661004e67f
commit 9c4515d9e7
6 changed files with 84 additions and 50 deletions

View File

@ -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);

View File

@ -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>

View File

@ -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&copy 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);

View File

@ -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&amp;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),
};
}
}

View 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),
};
}
}
}

View File

@ -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)