mirror of
https://github.com/chylex/Brotli-Builder.git
synced 2025-03-15 02:15:46 +01:00
Refactor Brotli element construction to guard mutability
This commit is contained in:
parent
d85badda47
commit
632f94eef9
BrotliLib/Brotli
Components
Contents
Data
Encode
@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using BrotliLib.Brotli.Components.Data;
|
||||
using BrotliLib.Brotli.Components.Utils;
|
||||
using BrotliLib.Brotli.Markers;
|
||||
@ -14,13 +15,15 @@ namespace BrotliLib.Brotli.Components.Contents.Compressed{
|
||||
|
||||
public InsertCopyLengths Lengths => new InsertCopyLengths(Literals.Count, CopyLength);
|
||||
|
||||
public InsertCopyCommand(IReadOnlyList<Literal> literals, int copyLength, DistanceInfo copyDistance = DistanceInfo.EndsAfterLiterals){
|
||||
this.Literals = literals;
|
||||
public InsertCopyCommand(IList<Literal> literals, int copyLength = InsertCopyLengths.MinCopyLength, DistanceInfo copyDistance = DistanceInfo.EndsAfterLiterals){
|
||||
this.Literals = literals.ToArray();
|
||||
this.CopyLength = copyLength;
|
||||
this.CopyDistance = copyDistance;
|
||||
|
||||
var _ = Lengths; // performs bounds checking
|
||||
}
|
||||
|
||||
public InsertCopyCommand(IReadOnlyList<Literal> literals, int copyLength, int copyDistance) : this(literals, copyLength, (DistanceInfo)copyDistance){}
|
||||
public InsertCopyCommand(IList<Literal> literals, int copyLength, int copyDistance) : this(literals, copyLength, (DistanceInfo)copyDistance){}
|
||||
|
||||
// Object
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using BrotliLib.Brotli.Components.Data;
|
||||
using BrotliLib.Brotli.Components.Header;
|
||||
using BrotliLib.Brotli.Components.Utils;
|
||||
@ -26,22 +27,22 @@ namespace BrotliLib.Brotli.Components.Contents.Compressed{
|
||||
CategoryMap<BlockTypeInfo> blockTypes,
|
||||
DistanceParameters distanceParameters,
|
||||
|
||||
IReadOnlyList<LiteralContextMode> literalCtxModes,
|
||||
IList<LiteralContextMode> literalCtxModes,
|
||||
ContextMap literalCtxMap,
|
||||
ContextMap distanceCtxMap,
|
||||
|
||||
IReadOnlyList<LiteralTree> literalTrees,
|
||||
IReadOnlyList<InsertCopyTree> insertCopyTrees,
|
||||
IReadOnlyList<DistanceTree> distanceTrees
|
||||
IList<LiteralTree> literalTrees,
|
||||
IList<InsertCopyTree> insertCopyTrees,
|
||||
IList<DistanceTree> distanceTrees
|
||||
){
|
||||
this.BlockTypes = blockTypes;
|
||||
this.DistanceParameters = distanceParameters;
|
||||
this.LiteralCtxModes = literalCtxModes;
|
||||
this.LiteralCtxModes = literalCtxModes.ToArray();
|
||||
this.LiteralCtxMap = literalCtxMap;
|
||||
this.DistanceCtxMap = distanceCtxMap;
|
||||
this.LiteralTrees = literalTrees;
|
||||
this.InsertCopyTrees = insertCopyTrees;
|
||||
this.DistanceTrees = distanceTrees;
|
||||
this.LiteralTrees = literalTrees.ToArray();
|
||||
this.InsertCopyTrees = insertCopyTrees.ToArray();
|
||||
this.DistanceTrees = distanceTrees.ToArray();
|
||||
}
|
||||
|
||||
// Object
|
||||
@ -83,7 +84,7 @@ namespace BrotliLib.Brotli.Components.Contents.Compressed{
|
||||
return ContextMap.Serializer.FromBits(reader, blockTypes[category]);
|
||||
}
|
||||
|
||||
private static IReadOnlyList<HuffmanTree<T>> ReadHuffmanTrees<T>(MarkedBitReader reader, Category category, int treeCount, HuffmanTree<T>.Context context) where T : IComparable<T>{
|
||||
private static IList<HuffmanTree<T>> ReadHuffmanTrees<T>(MarkedBitReader reader, Category category, int treeCount, HuffmanTree<T>.Context context) where T : IComparable<T>{
|
||||
return reader.ReadStructureArray(treeCount, HuffmanTree<T>.Serializer, context, "HTREE" + category.Id());
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using BrotliLib.Brotli.Components.Contents.Compressed;
|
||||
using BrotliLib.Brotli.Components.Data;
|
||||
using BrotliLib.Brotli.Components.Utils;
|
||||
@ -6,6 +7,7 @@ using BrotliLib.Brotli.Markers;
|
||||
using BrotliLib.Brotli.Markers.Data;
|
||||
using BrotliLib.IO;
|
||||
using BlockSwitchCommandMap = BrotliLib.Brotli.Components.Utils.CategoryMap<System.Collections.Generic.IReadOnlyList<BrotliLib.Brotli.Components.Contents.Compressed.BlockSwitchCommand>>;
|
||||
using BlockSwitchCommandMutableMap = BrotliLib.Brotli.Components.Utils.CategoryMap<System.Collections.Generic.IList<BrotliLib.Brotli.Components.Contents.Compressed.BlockSwitchCommand>>;
|
||||
|
||||
namespace BrotliLib.Brotli.Components.Contents{
|
||||
public sealed class CompressedMetaBlockContents{
|
||||
@ -13,10 +15,10 @@ namespace BrotliLib.Brotli.Components.Contents{
|
||||
public IReadOnlyList<InsertCopyCommand> InsertCopyCommands { get; }
|
||||
public BlockSwitchCommandMap BlockSwitchCommands { get; }
|
||||
|
||||
public CompressedMetaBlockContents(MetaBlockCompressionHeader header, IReadOnlyList<InsertCopyCommand> insertCopyCommands, BlockSwitchCommandMap blockSwitchCommands){
|
||||
public CompressedMetaBlockContents(MetaBlockCompressionHeader header, IList<InsertCopyCommand> insertCopyCommands, BlockSwitchCommandMutableMap blockSwitchCommands){
|
||||
this.Header = header;
|
||||
this.InsertCopyCommands = insertCopyCommands;
|
||||
this.BlockSwitchCommands = blockSwitchCommands;
|
||||
this.InsertCopyCommands = insertCopyCommands.ToArray();
|
||||
this.BlockSwitchCommands = blockSwitchCommands.Select<IReadOnlyList<BlockSwitchCommand>>((_, list) => list.ToArray());
|
||||
}
|
||||
|
||||
// Object
|
||||
@ -66,14 +68,13 @@ namespace BrotliLib.Brotli.Components.Contents{
|
||||
}
|
||||
|
||||
private class ReaderDataContext : DataContext{
|
||||
public BlockSwitchCommandMap BlockSwitchCommands => blockSwitchCommands.Select<IReadOnlyList<BlockSwitchCommand>>((_, list) => list.AsReadOnly());
|
||||
public BlockSwitchCommandMutableMap BlockSwitchCommands { get; }
|
||||
|
||||
private readonly MarkedBitReader reader;
|
||||
private readonly CategoryMap<List<BlockSwitchCommand>> blockSwitchCommands;
|
||||
|
||||
public ReaderDataContext(MetaBlock.Context wrapped, MetaBlockCompressionHeader header, MarkedBitReader reader) : base(wrapped, header){
|
||||
this.reader = reader;
|
||||
this.blockSwitchCommands = new CategoryMap<List<BlockSwitchCommand>>(_ => new List<BlockSwitchCommand>());
|
||||
this.BlockSwitchCommands = new CategoryMap<IList<BlockSwitchCommand>>(_ => new List<BlockSwitchCommand>());
|
||||
}
|
||||
|
||||
public override int NextBlockID(Category category){
|
||||
@ -81,7 +82,7 @@ namespace BrotliLib.Brotli.Components.Contents{
|
||||
BlockSwitchCommand nextCommand = tracker.ReadCommand(reader);
|
||||
|
||||
if (nextCommand != null){
|
||||
blockSwitchCommands[category].Add(nextCommand);
|
||||
BlockSwitchCommands[category].Add(nextCommand);
|
||||
}
|
||||
|
||||
return tracker.CurrentID;
|
||||
@ -121,7 +122,7 @@ namespace BrotliLib.Brotli.Components.Contents{
|
||||
|
||||
reader.MarkEnd(new TitleMarker("Command List"));
|
||||
|
||||
return new CompressedMetaBlockContents(header, icCommands.ToArray(), dataContext.BlockSwitchCommands);
|
||||
return new CompressedMetaBlockContents(header, icCommands, dataContext.BlockSwitchCommands);
|
||||
},
|
||||
|
||||
toBits: (writer, obj, context) => {
|
||||
|
@ -13,7 +13,7 @@ namespace BrotliLib.Brotli.Components.Data{
|
||||
public static readonly AlphabetSize AlphabetSize = new AlphabetSize(256);
|
||||
public static readonly LiteralTree.Context TreeContext = new LiteralTree.Context(AlphabetSize, value => new Literal((byte)value), symbol => symbol.Value);
|
||||
|
||||
public static IReadOnlyList<Literal> FromBytes(byte[] bytes){
|
||||
public static IList<Literal> FromBytes(byte[] bytes){
|
||||
return Array.ConvertAll(bytes, b => new Literal(b));
|
||||
}
|
||||
|
||||
|
@ -22,8 +22,8 @@ namespace BrotliLib.Brotli.Encode{
|
||||
public ContextMap LiteralCtxMap { get; set; } = ContextMap.Literals.Simple;
|
||||
public ContextMap DistanceCtxMap { get; set; } = ContextMap.Distances.Simple;
|
||||
|
||||
private readonly List<InsertCopyCommand> icCommands = new List<InsertCopyCommand>();
|
||||
private readonly CategoryMap<List<BlockSwitchCommand>> bsCommands = new CategoryMap<List<BlockSwitchCommand>>(_ => new List<BlockSwitchCommand>());
|
||||
private readonly IList<InsertCopyCommand> icCommands = new List<InsertCopyCommand>();
|
||||
private readonly CategoryMap<IList<BlockSwitchCommand>> bsCommands = new CategoryMap<IList<BlockSwitchCommand>>(_ => new List<BlockSwitchCommand>());
|
||||
|
||||
private readonly BrotliGlobalState initialState;
|
||||
private readonly BrotliGlobalState intermediateState;
|
||||
@ -162,7 +162,7 @@ namespace BrotliLib.Brotli.Encode{
|
||||
);
|
||||
|
||||
var metaBlock = new MetaBlock.Compressed(isLast: false, new DataLength(OutputSize)){
|
||||
Contents = new CompressedMetaBlockContents(header, icCommands, bsCommands.Select<IReadOnlyList<BlockSwitchCommand>>((_, list) => list.AsReadOnly()))
|
||||
Contents = new CompressedMetaBlockContents(header, icCommands, bsCommands)
|
||||
};
|
||||
|
||||
return (metaBlock, () => new CompressedMetaBlockBuilder(state));
|
||||
|
Loading…
Reference in New Issue
Block a user