misc/libphysfs/lzma/CPP/7zip/Compress/RangeCoder/RangeCoder.h
changeset 13881 99b265e0d1d0
parent 13880 5f819b90d479
child 13882 b172a5d40eee
equal deleted inserted replaced
13880:5f819b90d479 13881:99b265e0d1d0
     1 // Compress/RangeCoder/RangeCoder.h
       
     2 
       
     3 #ifndef __COMPRESS_RANGECODER_H
       
     4 #define __COMPRESS_RANGECODER_H
       
     5 
       
     6 #include "../../Common/InBuffer.h"
       
     7 #include "../../Common/OutBuffer.h"
       
     8 
       
     9 namespace NCompress {
       
    10 namespace NRangeCoder {
       
    11 
       
    12 const int kNumTopBits = 24;
       
    13 const UInt32 kTopValue = (1 << kNumTopBits);
       
    14 
       
    15 class CEncoder
       
    16 {
       
    17   UInt32 _cacheSize;
       
    18   Byte _cache;
       
    19 public:
       
    20   UInt64 Low;
       
    21   UInt32 Range;
       
    22   COutBuffer Stream;
       
    23   bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); }
       
    24 
       
    25   void SetStream(ISequentialOutStream *stream) { Stream.SetStream(stream); }
       
    26   void Init()
       
    27   {
       
    28     Stream.Init();
       
    29     Low = 0;
       
    30     Range = 0xFFFFFFFF;
       
    31     _cacheSize = 1;
       
    32     _cache = 0;
       
    33   }
       
    34 
       
    35   void FlushData()
       
    36   {
       
    37     // Low += 1; 
       
    38     for(int i = 0; i < 5; i++)
       
    39       ShiftLow();
       
    40   }
       
    41 
       
    42   HRESULT FlushStream() { return Stream.Flush();  }
       
    43 
       
    44   void ReleaseStream() { Stream.ReleaseStream(); }
       
    45 
       
    46   void Encode(UInt32 start, UInt32 size, UInt32 total)
       
    47   {
       
    48     Low += start * (Range /= total);
       
    49     Range *= size;
       
    50     while (Range < kTopValue)
       
    51     {
       
    52       Range <<= 8;
       
    53       ShiftLow();
       
    54     }
       
    55   }
       
    56 
       
    57   void ShiftLow()
       
    58   {
       
    59     if ((UInt32)Low < (UInt32)0xFF000000 || (int)(Low >> 32) != 0) 
       
    60     {
       
    61       Byte temp = _cache;
       
    62       do
       
    63       {
       
    64         Stream.WriteByte((Byte)(temp + (Byte)(Low >> 32)));
       
    65         temp = 0xFF;
       
    66       }
       
    67       while(--_cacheSize != 0);
       
    68       _cache = (Byte)((UInt32)Low >> 24);                      
       
    69     } 
       
    70     _cacheSize++;                               
       
    71     Low = (UInt32)Low << 8;                           
       
    72   }
       
    73   
       
    74   void EncodeDirectBits(UInt32 value, int numTotalBits)
       
    75   {
       
    76     for (int i = numTotalBits - 1; i >= 0; i--)
       
    77     {
       
    78       Range >>= 1;
       
    79       if (((value >> i) & 1) == 1)
       
    80         Low += Range;
       
    81       if (Range < kTopValue)
       
    82       {
       
    83         Range <<= 8;
       
    84         ShiftLow();
       
    85       }
       
    86     }
       
    87   }
       
    88 
       
    89   void EncodeBit(UInt32 size0, UInt32 numTotalBits, UInt32 symbol)
       
    90   {
       
    91     UInt32 newBound = (Range >> numTotalBits) * size0;
       
    92     if (symbol == 0)
       
    93       Range = newBound;
       
    94     else
       
    95     {
       
    96       Low += newBound;
       
    97       Range -= newBound;
       
    98     }
       
    99     while (Range < kTopValue)
       
   100     {
       
   101       Range <<= 8;
       
   102       ShiftLow();
       
   103     }
       
   104   }
       
   105 
       
   106   UInt64 GetProcessedSize() {  return Stream.GetProcessedSize() + _cacheSize + 4; }
       
   107 };
       
   108 
       
   109 class CDecoder
       
   110 {
       
   111 public:
       
   112   CInBuffer Stream;
       
   113   UInt32 Range;
       
   114   UInt32 Code;
       
   115   bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); }
       
   116 
       
   117   void Normalize()
       
   118   {
       
   119     while (Range < kTopValue)
       
   120     {
       
   121       Code = (Code << 8) | Stream.ReadByte();
       
   122       Range <<= 8;
       
   123     }
       
   124   }
       
   125   
       
   126   void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); }
       
   127   void Init()
       
   128   {
       
   129     Stream.Init();
       
   130     Code = 0;
       
   131     Range = 0xFFFFFFFF;
       
   132     for(int i = 0; i < 5; i++)
       
   133       Code = (Code << 8) | Stream.ReadByte();
       
   134   }
       
   135 
       
   136   void ReleaseStream() { Stream.ReleaseStream(); }
       
   137 
       
   138   UInt32 GetThreshold(UInt32 total)
       
   139   {
       
   140     return (Code) / ( Range /= total);
       
   141   }
       
   142 
       
   143   void Decode(UInt32 start, UInt32 size)
       
   144   {
       
   145     Code -= start * Range;
       
   146     Range *= size;
       
   147     Normalize();
       
   148   }
       
   149 
       
   150   UInt32 DecodeDirectBits(int numTotalBits)
       
   151   {
       
   152     UInt32 range = Range;
       
   153     UInt32 code = Code;        
       
   154     UInt32 result = 0;
       
   155     for (int i = numTotalBits; i != 0; i--)
       
   156     {
       
   157       range >>= 1;
       
   158       /*
       
   159       result <<= 1;
       
   160       if (code >= range)
       
   161       {
       
   162         code -= range;
       
   163         result |= 1;
       
   164       }
       
   165       */
       
   166       UInt32 t = (code - range) >> 31;
       
   167       code -= range & (t - 1);
       
   168       result = (result << 1) | (1 - t);
       
   169 
       
   170       if (range < kTopValue)
       
   171       {
       
   172         code = (code << 8) | Stream.ReadByte();
       
   173         range <<= 8; 
       
   174       }
       
   175     }
       
   176     Range = range;
       
   177     Code = code;
       
   178     return result;
       
   179   }
       
   180 
       
   181   UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits)
       
   182   {
       
   183     UInt32 newBound = (Range >> numTotalBits) * size0;
       
   184     UInt32 symbol;
       
   185     if (Code < newBound)
       
   186     {
       
   187       symbol = 0;
       
   188       Range = newBound;
       
   189     }
       
   190     else
       
   191     {
       
   192       symbol = 1;
       
   193       Code -= newBound;
       
   194       Range -= newBound;
       
   195     }
       
   196     Normalize();
       
   197     return symbol;
       
   198   }
       
   199 
       
   200   UInt64 GetProcessedSize() {return Stream.GetProcessedSize(); }
       
   201 };
       
   202 
       
   203 }}
       
   204 
       
   205 #endif