1
0
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:
chylex 2019-05-16 18:25:30 +02:00
parent d85badda47
commit 632f94eef9
5 changed files with 29 additions and 24 deletions

View File

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

View File

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

View File

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

View File

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

View File

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