1
0
mirror of https://github.com/chylex/Brotli-Builder.git synced 2024-12-22 16:42:46 +01:00
Brotli-Builder/BrotliLib/Serialization/Writer/BitWriter.cs

83 lines
2.6 KiB
C#

using System;
using BrotliLib.Collections.Huffman;
namespace BrotliLib.Serialization.Writer{
public class BitWriter : IBitWriter{
private const int MaxChunkSize = BitStream.ByteSize * sizeof(int);
private readonly BitStream stream;
/// <summary>
/// Initializes a new <see cref="BitWriter"/> at the end of the specified <see cref="BitStream"/>.
/// </summary>
/// <param name="stream">Input bit stream.</param>
public BitWriter(BitStream stream){
this.stream = stream;
}
public void WriteBit(bool bit){
stream.Add(bit);
}
public void WriteBits(BitStream bits){
stream.AddAll(bits);
}
public void WriteBits(in BitPath bits){
for(int index = 0; index < bits.Length; index++){
stream.Add(bits[index]);
}
}
public void WriteChunk(int count, int value){
if (count > MaxChunkSize){
throw new ArgumentOutOfRangeException(nameof(count), "Cannot write a chunk larger than " + MaxChunkSize + " bits in one call.");
}
for(int index = 0; index < count; index++){
stream.Add((value & (1 << index)) != 0);
}
}
public void AlignToByteBoundary(){
long relativeIndex = stream.Length & BitStream.ByteMask;
if (relativeIndex > 0){
for(long bitsLeft = BitStream.ByteSize - relativeIndex; bitsLeft > 0; bitsLeft--){
stream.Add(false);
}
}
}
public void WriteAlignedBytes(byte[] bytes){
AlignToByteBoundary();
int index = 0;
while(index < bytes.Length && stream.Length % BitStream.BitEntrySize != 0){
stream.AddByte(bytes[index]);
++index;
}
while(index < bytes.Length - BitStream.BytesPerEntry){
ulong value = bytes[index];
value |= (ulong)bytes[index + 1] << 8;
value |= (ulong)bytes[index + 2] << 16;
value |= (ulong)bytes[index + 3] << 24;
value |= (ulong)bytes[index + 4] << 32;
value |= (ulong)bytes[index + 5] << 40;
value |= (ulong)bytes[index + 6] << 48;
value |= (ulong)bytes[index + 7] << 56;
stream.AddLong(value);
index += BitStream.BytesPerEntry;
}
while(index < bytes.Length){
stream.AddByte(bytes[index]);
++index;
}
}
}
}