tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

RangeCoder.cs (4190B)


      1 using System;
      2 
      3 namespace SevenZip.Compression.RangeCoder
      4 {
      5 class Encoder
      6 {
      7 	public const uint kTopValue = (1 << 24);
      8 
      9 	System.IO.Stream Stream;
     10 
     11 	public UInt64 Low;
     12 	public uint Range;
     13 	uint _cacheSize;
     14 	byte _cache;
     15 
     16 	long StartPosition;
     17 
     18 	public void SetStream(System.IO.Stream stream)
     19 	{
     20 		Stream = stream;
     21 	}
     22 
     23 	public void ReleaseStream()
     24 	{
     25 		Stream = null;
     26 	}
     27 
     28 	public void Init()
     29 	{
     30 		StartPosition = Stream.Position;
     31 
     32 		Low = 0;
     33 		Range = 0xFFFFFFFF;
     34 		_cacheSize = 1;
     35 		_cache = 0;
     36 	}
     37 
     38 	public void FlushData()
     39 	{
     40 		for (int i = 0; i < 5; i++)
     41 			ShiftLow();
     42 	}
     43 
     44 	public void FlushStream()
     45 	{
     46 		Stream.Flush();
     47 	}
     48 
     49 	public void CloseStream()
     50 	{
     51 		Stream.Close();
     52 	}
     53 
     54 	public void Encode(uint start, uint size, uint total)
     55 	{
     56 		Low += start * (Range /= total);
     57 		Range *= size;
     58 		while (Range < kTopValue)
     59 		{
     60 			Range <<= 8;
     61 			ShiftLow();
     62 		}
     63 	}
     64 
     65 	public void ShiftLow()
     66 	{
     67 		if ((uint)Low < (uint)0xFF000000 || (uint)(Low >> 32) == 1)
     68 		{
     69 			byte temp = _cache;
     70 			do
     71 			{
     72 				Stream.WriteByte((byte)(temp + (Low >> 32)));
     73 				temp = 0xFF;
     74 			}
     75 			while (--_cacheSize != 0);
     76 			_cache = (byte)(((uint)Low) >> 24);
     77 		}
     78 		_cacheSize++;
     79 		Low = ((uint)Low) << 8;
     80 	}
     81 
     82 	public void EncodeDirectBits(uint v, int numTotalBits)
     83 	{
     84 		for (int i = numTotalBits - 1; i >= 0; i--)
     85 		{
     86 			Range >>= 1;
     87 			if (((v >> i) & 1) == 1)
     88 				Low += Range;
     89 			if (Range < kTopValue)
     90 			{
     91 				Range <<= 8;
     92 				ShiftLow();
     93 			}
     94 		}
     95 	}
     96 
     97 	public void EncodeBit(uint size0, int numTotalBits, uint symbol)
     98 	{
     99 		uint newBound = (Range >> numTotalBits) * size0;
    100 		if (symbol == 0)
    101 			Range = newBound;
    102 		else
    103 		{
    104 			Low += newBound;
    105 			Range -= newBound;
    106 		}
    107 		while (Range < kTopValue)
    108 		{
    109 			Range <<= 8;
    110 			ShiftLow();
    111 		}
    112 	}
    113 
    114 	public long GetProcessedSizeAdd()
    115 	{
    116 		return _cacheSize +
    117 			Stream.Position - StartPosition + 4;
    118 		// (long)Stream.GetProcessedSize();
    119 	}
    120 }
    121 
    122 class Decoder
    123 {
    124 	public const uint kTopValue = (1 << 24);
    125 	public uint Range;
    126 	public uint Code;
    127 	// public Buffer.InBuffer Stream = new Buffer.InBuffer(1 << 16);
    128 	public System.IO.Stream Stream;
    129 
    130 	public void Init(System.IO.Stream stream)
    131 	{
    132 		// Stream.Init(stream);
    133 		Stream = stream;
    134 
    135 		Code = 0;
    136 		Range = 0xFFFFFFFF;
    137 		for (int i = 0; i < 5; i++)
    138 			Code = (Code << 8) | (byte)Stream.ReadByte();
    139 	}
    140 
    141 	public void ReleaseStream()
    142 	{
    143 		// Stream.ReleaseStream();
    144 		Stream = null;
    145 	}
    146 
    147 	public void CloseStream()
    148 	{
    149 		Stream.Close();
    150 	}
    151 
    152 	public void Normalize()
    153 	{
    154 		while (Range < kTopValue)
    155 		{
    156 			Code = (Code << 8) | (byte)Stream.ReadByte();
    157 			Range <<= 8;
    158 		}
    159 	}
    160 
    161 	public void Normalize2()
    162 	{
    163 		if (Range < kTopValue)
    164 		{
    165 			Code = (Code << 8) | (byte)Stream.ReadByte();
    166 			Range <<= 8;
    167 		}
    168 	}
    169 
    170 	public uint GetThreshold(uint total)
    171 	{
    172 		return Code / (Range /= total);
    173 	}
    174 
    175 	public void Decode(uint start, uint size, uint total)
    176 	{
    177 		Code -= start * Range;
    178 		Range *= size;
    179 		Normalize();
    180 	}
    181 
    182 	public uint DecodeDirectBits(int numTotalBits)
    183 	{
    184 		uint range = Range;
    185 		uint code = Code;
    186 		uint result = 0;
    187 		for (int i = numTotalBits; i > 0; i--)
    188 		{
    189 			range >>= 1;
    190 			/*
    191 			result <<= 1;
    192 			if (code >= range)
    193 			{
    194 				code -= range;
    195 				result |= 1;
    196 			}
    197 			*/
    198 			uint t = (code - range) >> 31;
    199 			code -= range & (t - 1);
    200 			result = (result << 1) | (1 - t);
    201 
    202 			if (range < kTopValue)
    203 			{
    204 				code = (code << 8) | (byte)Stream.ReadByte();
    205 				range <<= 8;
    206 			}
    207 		}
    208 		Range = range;
    209 		Code = code;
    210 		return result;
    211 	}
    212 
    213 	public uint DecodeBit(uint size0, int numTotalBits)
    214 	{
    215 		uint newBound = (Range >> numTotalBits) * size0;
    216 		uint symbol;
    217 		if (Code < newBound)
    218 		{
    219 			symbol = 0;
    220 			Range = newBound;
    221 		}
    222 		else
    223 		{
    224 			symbol = 1;
    225 			Code -= newBound;
    226 			Range -= newBound;
    227 		}
    228 		Normalize();
    229 		return symbol;
    230 	}
    231 
    232 	// ulong GetProcessedSize() {return Stream.GetProcessedSize(); }
    233 }
    234 }