misc/libphysfs/lzma/CS/7zip/Compress/RangeCoder/RangeCoder.cs
branchui-scaling
changeset 15283 c4fd2813b127
parent 13390 0135e64c6c66
parent 15279 7ab5cf405686
child 15663 d92eeb468dad
equal deleted inserted replaced
13390:0135e64c6c66 15283:c4fd2813b127
     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 }