mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-02-14 21:23:38 +00:00
103 lines
2.8 KiB
C#
103 lines
2.8 KiB
C#
#region Using
|
|
|
|
using System;
|
|
using System.IO;
|
|
|
|
#endregion
|
|
|
|
namespace SharpCompress.Compressor.PPMd.I1
|
|
{
|
|
/// <summary>
|
|
/// A simple range coder.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Note that in most cases fields are used rather than properties for performance reasons (for example,
|
|
/// <see cref="Scale"/> is a field rather than a property).
|
|
/// </remarks>
|
|
internal class Coder
|
|
{
|
|
private const uint RangeTop = 1 << 24;
|
|
private const uint RangeBottom = 1 << 15;
|
|
private uint low;
|
|
private uint code;
|
|
private uint range;
|
|
|
|
public uint LowCount;
|
|
public uint HighCount;
|
|
public uint Scale;
|
|
|
|
public void RangeEncoderInitialize()
|
|
{
|
|
low = 0;
|
|
range = uint.MaxValue;
|
|
}
|
|
|
|
public void RangeEncoderNormalize(Stream stream)
|
|
{
|
|
while ((low ^ (low + range)) < RangeTop ||
|
|
range < RangeBottom && ((range = (uint) -low & (RangeBottom - 1)) != 0 || true))
|
|
{
|
|
stream.WriteByte((byte) (low >> 24));
|
|
range <<= 8;
|
|
low <<= 8;
|
|
}
|
|
}
|
|
|
|
public void RangeEncodeSymbol()
|
|
{
|
|
low += LowCount*(range /= Scale);
|
|
range *= HighCount - LowCount;
|
|
}
|
|
|
|
public void RangeShiftEncodeSymbol(int rangeShift)
|
|
{
|
|
low += LowCount*(range >>= rangeShift);
|
|
range *= HighCount - LowCount;
|
|
}
|
|
|
|
public void RangeEncoderFlush(Stream stream)
|
|
{
|
|
for (uint index = 0; index < 4; index++)
|
|
{
|
|
stream.WriteByte((byte) (low >> 24));
|
|
low <<= 8;
|
|
}
|
|
}
|
|
|
|
public void RangeDecoderInitialize(Stream stream)
|
|
{
|
|
low = 0;
|
|
code = 0;
|
|
range = uint.MaxValue;
|
|
for (uint index = 0; index < 4; index++)
|
|
code = (code << 8) | (byte) stream.ReadByte();
|
|
}
|
|
|
|
public void RangeDecoderNormalize(Stream stream)
|
|
{
|
|
while ((low ^ (low + range)) < RangeTop ||
|
|
range < RangeBottom && ((range = (uint) -low & (RangeBottom - 1)) != 0 || true))
|
|
{
|
|
code = (code << 8) | (byte) stream.ReadByte();
|
|
range <<= 8;
|
|
low <<= 8;
|
|
}
|
|
}
|
|
|
|
public uint RangeGetCurrentCount()
|
|
{
|
|
return (code - low)/(range /= Scale);
|
|
}
|
|
|
|
public uint RangeGetCurrentShiftCount(int rangeShift)
|
|
{
|
|
return (code - low)/(range >>= rangeShift);
|
|
}
|
|
|
|
public void RangeRemoveSubrange()
|
|
{
|
|
low += range*LowCount;
|
|
range *= HighCount - LowCount;
|
|
}
|
|
}
|
|
} |