Home | History | Annotate | Download | only in RangeCoder
      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 }
    235