misc/libphysfs/lzma/Java/SevenZip/Compression/RangeCoder/Encoder.java
author nemo
Mon, 10 Apr 2017 12:06:43 -0400
changeset 12218 bb5522e88ab2
permissions -rw-r--r--
bulk copy of latest physfs to our misc/libphysfs since this seems to fix an off-by-1 error reliably hit in readln read of 1 byte probably introduced in the addition of the buffered read. Whether this is excessive or whether libphysfs should even be maintained by us is another matter. But at least we shouldn't crash

package SevenZip.Compression.RangeCoder;
import java.io.IOException;

public class Encoder
{
	static final int kTopMask = ~((1 << 24) - 1);
	
	static final int kNumBitModelTotalBits = 11;
	static final int kBitModelTotal = (1 << kNumBitModelTotalBits);
	static final int kNumMoveBits = 5;
	
	java.io.OutputStream Stream;

	long Low;
	int Range;
	int _cacheSize;
	int _cache;
	
	long _position;
	
	public void SetStream(java.io.OutputStream stream)
	{
		Stream = stream;
	}
	
	public void ReleaseStream()
	{
		Stream = null;
	}
	
	public void Init()
	{
		_position = 0;
		Low = 0;
		Range = -1;
		_cacheSize = 1;
		_cache = 0;
	}
	
	public void FlushData() throws IOException
	{
		for (int i = 0; i < 5; i++)
			ShiftLow();
	}
	
	public void FlushStream() throws IOException
	{
		Stream.flush();
	}
	
	public void ShiftLow() throws IOException
	{
		int LowHi = (int)(Low >>> 32);
		if (LowHi != 0 || Low < 0xFF000000L)
		{
			_position += _cacheSize;
			int temp = _cache;
			do
			{
				Stream.write(temp + LowHi);
				temp = 0xFF;
			}
			while(--_cacheSize != 0);
			_cache = (((int)Low) >>> 24);
		}
		_cacheSize++;
		Low = (Low & 0xFFFFFF) << 8;
	}
	
	public void EncodeDirectBits(int v, int numTotalBits) throws IOException
	{
		for (int i = numTotalBits - 1; i >= 0; i--)
		{
			Range >>>= 1;
			if (((v >>> i) & 1) == 1)
				Low += Range;
			if ((Range & Encoder.kTopMask) == 0)
			{
				Range <<= 8;
				ShiftLow();
			}
		}
	}
	
	
	public long GetProcessedSizeAdd()
	{
		return _cacheSize + _position + 4;
	}
	
	
	
	static final int kNumMoveReducingBits = 2;
	public static final int kNumBitPriceShiftBits = 6;
	
	public static void InitBitModels(short []probs)
	{
		for (int i = 0; i < probs.length; i++)
			probs[i] = (kBitModelTotal >>> 1);
	}
	
	public void Encode(short []probs, int index, int symbol) throws IOException
	{
		int prob = probs[index];
		int newBound = (Range >>> kNumBitModelTotalBits) * prob;
		if (symbol == 0)
		{
			Range = newBound;
			probs[index] = (short)(prob + ((kBitModelTotal - prob) >>> kNumMoveBits));
		}
		else
		{
			Low += (newBound & 0xFFFFFFFFL);
			Range -= newBound;
			probs[index] = (short)(prob - ((prob) >>> kNumMoveBits));
		}
		if ((Range & kTopMask) == 0)
		{
			Range <<= 8;
			ShiftLow();
		}
	}
	
	private static int[] ProbPrices = new int[kBitModelTotal >>> kNumMoveReducingBits];
	
	static
	{
		int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits);
		for (int i = kNumBits - 1; i >= 0; i--)
		{
			int start = 1 << (kNumBits - i - 1);
			int end = 1 << (kNumBits - i);
			for (int j = start; j < end; j++)
				ProbPrices[j] = (i << kNumBitPriceShiftBits) +
						(((end - j) << kNumBitPriceShiftBits) >>> (kNumBits - i - 1));
		}
	}
	
	static public int GetPrice(int Prob, int symbol)
	{
		return ProbPrices[(((Prob - symbol) ^ ((-symbol))) & (kBitModelTotal - 1)) >>> kNumMoveReducingBits];
	}
	static public int GetPrice0(int Prob)
	{ 
		return ProbPrices[Prob >>> kNumMoveReducingBits]; 
	}
	static public int GetPrice1(int Prob)
	{ 
		return ProbPrices[(kBitModelTotal - Prob) >>> kNumMoveReducingBits]; 
	}
}