other-licenses/7zstub/src/7zip/Compress/RangeCoder/RangeCoder.h

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 // Compress/RangeCoder/RangeCoder.h
     3 #ifndef __COMPRESS_RANGECODER_H
     4 #define __COMPRESS_RANGECODER_H
     6 #include "../../Common/InBuffer.h"
     7 #include "../../Common/OutBuffer.h"
     9 namespace NCompress {
    10 namespace NRangeCoder {
    12 const int kNumTopBits = 24;
    13 const UInt32 kTopValue = (1 << kNumTopBits);
    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); }
    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   }
    35   void FlushData()
    36   {
    37     // Low += 1; 
    38     for(int i = 0; i < 5; i++)
    39       ShiftLow();
    40   }
    42   HRESULT FlushStream() { return Stream.Flush();  }
    44   void ReleaseStream() { Stream.ReleaseStream(); }
    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   }
    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   }
    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   }
    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   }
   106   UInt64 GetProcessedSize() {  return Stream.GetProcessedSize() + _cacheSize + 4; }
   107 };
   109 class CDecoder
   110 {
   111 public:
   112   CInBuffer Stream;
   113   UInt32 Range;
   114   UInt32 Code;
   115   bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); }
   117   void Normalize()
   118   {
   119     while (Range < kTopValue)
   120     {
   121       Code = (Code << 8) | Stream.ReadByte();
   122       Range <<= 8;
   123     }
   124   }
   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   }
   136   void ReleaseStream() { Stream.ReleaseStream(); }
   138   UInt32 GetThreshold(UInt32 total)
   139   {
   140     return (Code) / ( Range /= total);
   141   }
   143   void Decode(UInt32 start, UInt32 size)
   144   {
   145     Code -= start * Range;
   146     Range *= size;
   147     Normalize();
   148   }
   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);
   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   }
   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   }
   200   UInt64 GetProcessedSize() {return Stream.GetProcessedSize(); }
   201 };
   203 }}
   205 #endif

mercurial