123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404 |
- #ifndef _RAR_UNPACK_
- #define _RAR_UNPACK_
- // Maximum allowed number of compressed bits processed in quick mode.
- #define MAX_QUICK_DECODE_BITS 10
- // Maximum number of filters per entire data block. Must be at least
- // twice more than MAX_PACK_FILTERS to store filters from two data blocks.
- #define MAX_UNPACK_FILTERS 8192
- // Maximum number of filters per entire data block for RAR3 unpack.
- // Must be at least twice more than v3_MAX_PACK_FILTERS to store filters
- // from two data blocks.
- #define MAX3_UNPACK_FILTERS 8192
- // Limit maximum number of channels in RAR3 delta filter to some reasonable
- // value to prevent too slow processing of corrupt archives with invalid
- // channels number. Must be equal or larger than v3_MAX_FILTER_CHANNELS.
- // No need to provide it for RAR5, which uses only 5 bits to store channels.
- #define MAX3_UNPACK_CHANNELS 1024
- // Maximum size of single filter block. We restrict it to limit memory
- // allocation. Must be equal or larger than MAX_ANALYZE_SIZE.
- #define MAX_FILTER_BLOCK_SIZE 0x400000
- // Write data in 4 MB or smaller blocks. Must not exceed PACK_MAX_READ,
- // so we keep the number of buffered filters in unpacker reasonable.
- #define UNPACK_MAX_WRITE 0x400000
- // Decode compressed bit fields to alphabet numbers.
- struct DecodeTable:PackDef
- {
- // Real size of DecodeNum table.
- uint MaxNum;
- // Left aligned start and upper limit codes defining code space
- // ranges for bit lengths. DecodeLen[BitLength-1] defines the start of
- // range for bit length and DecodeLen[BitLength] defines next code
- // after the end of range or in other words the upper limit code
- // for specified bit length.
- uint DecodeLen[16];
- // Every item of this array contains the sum of all preceding items.
- // So it contains the start position in code list for every bit length.
- uint DecodePos[16];
- // Number of compressed bits processed in quick mode.
- // Must not exceed MAX_QUICK_DECODE_BITS.
- uint QuickBits;
- // Translates compressed bits (up to QuickBits length)
- // to bit length in quick mode.
- byte QuickLen[1<<MAX_QUICK_DECODE_BITS];
- // Translates compressed bits (up to QuickBits length)
- // to position in alphabet in quick mode.
- // 'ushort' saves some memory and even provides a little speed gain
- // comparting to 'uint' here.
- ushort QuickNum[1<<MAX_QUICK_DECODE_BITS];
- // Translate the position in code list to position in alphabet.
- // We do not allocate it dynamically to avoid performance overhead
- // introduced by pointer, so we use the largest possible table size
- // as array dimension. Real size of this array is defined in MaxNum.
- // We use this array if compressed bit field is too lengthy
- // for QuickLen based translation.
- // 'ushort' saves some memory and even provides a little speed gain
- // comparting to 'uint' here.
- ushort DecodeNum[LARGEST_TABLE_SIZE];
- };
- struct UnpackBlockHeader
- {
- int BlockSize;
- int BlockBitSize;
- int BlockStart;
- int HeaderSize;
- bool LastBlockInFile;
- bool TablePresent;
- };
- struct UnpackBlockTables
- {
- DecodeTable LD; // Decode literals.
- DecodeTable DD; // Decode distances.
- DecodeTable LDD; // Decode lower bits of distances.
- DecodeTable RD; // Decode repeating distances.
- DecodeTable BD; // Decode bit lengths in Huffman table.
- };
- #ifdef RAR_SMP
- enum UNP_DEC_TYPE {
- UNPDT_LITERAL,UNPDT_MATCH,UNPDT_FULLREP,UNPDT_REP,UNPDT_FILTER
- };
- struct UnpackDecodedItem
- {
- UNP_DEC_TYPE Type;
- ushort Length;
- union
- {
- uint Distance;
- byte Literal[4];
- };
- };
- struct UnpackThreadData
- {
- Unpack *UnpackPtr;
- BitInput Inp;
- bool HeaderRead;
- UnpackBlockHeader BlockHeader;
- bool TableRead;
- UnpackBlockTables BlockTables;
- int DataSize; // Data left in buffer. Can be less than block size.
- bool DamagedData;
- bool LargeBlock;
- bool NoDataLeft; // 'true' if file is read completely.
- bool Incomplete; // Not entire block was processed, need to read more data.
- UnpackDecodedItem *Decoded;
- uint DecodedSize;
- uint DecodedAllocated;
- uint ThreadNumber; // For debugging.
- UnpackThreadData()
- :Inp(false)
- {
- Decoded=NULL;
- }
- ~UnpackThreadData()
- {
- if (Decoded!=NULL)
- free(Decoded);
- }
- };
- #endif
- struct UnpackFilter
- {
- byte Type;
- uint BlockStart;
- uint BlockLength;
- byte Channels;
- // uint Width;
- // byte PosR;
- bool NextWindow;
- };
- struct UnpackFilter30
- {
- unsigned int BlockStart;
- unsigned int BlockLength;
- bool NextWindow;
- // Position of parent filter in Filters array used as prototype for filter
- // in PrgStack array. Not defined for filters in Filters array.
- unsigned int ParentFilter;
- VM_PreparedProgram Prg;
- };
- struct AudioVariables // For RAR 2.0 archives only.
- {
- int K1,K2,K3,K4,K5;
- int D1,D2,D3,D4;
- int LastDelta;
- unsigned int Dif[11];
- unsigned int ByteCount;
- int LastChar;
- };
- // We can use the fragmented dictionary in case heap does not have the single
- // large enough memory block. It is slower than normal dictionary.
- class FragmentedWindow
- {
- private:
- enum {MAX_MEM_BLOCKS=32};
- void Reset();
- byte *Mem[MAX_MEM_BLOCKS];
- size_t MemSize[MAX_MEM_BLOCKS];
- public:
- FragmentedWindow();
- ~FragmentedWindow();
- void Init(size_t WinSize);
- byte& operator [](size_t Item);
- void CopyString(uint Length,uint Distance,size_t &UnpPtr,size_t MaxWinMask);
- void CopyData(byte *Dest,size_t WinPos,size_t Size);
- size_t GetBlockSize(size_t StartPos,size_t RequiredSize);
- };
- class Unpack:PackDef
- {
- private:
- void Unpack5(bool Solid);
- void Unpack5MT(bool Solid);
- bool UnpReadBuf();
- void UnpWriteBuf();
- byte* ApplyFilter(byte *Data,uint DataSize,UnpackFilter *Flt);
- void UnpWriteArea(size_t StartPtr,size_t EndPtr);
- void UnpWriteData(byte *Data,size_t Size);
- _forceinline uint SlotToLength(BitInput &Inp,uint Slot);
- void UnpInitData50(bool Solid);
- bool ReadBlockHeader(BitInput &Inp,UnpackBlockHeader &Header);
- bool ReadTables(BitInput &Inp,UnpackBlockHeader &Header,UnpackBlockTables &Tables);
- void MakeDecodeTables(byte *LengthTable,DecodeTable *Dec,uint Size);
- _forceinline uint DecodeNumber(BitInput &Inp,DecodeTable *Dec);
- void CopyString();
- inline void InsertOldDist(unsigned int Distance);
- void UnpInitData(bool Solid);
- _forceinline void CopyString(uint Length,uint Distance);
- uint ReadFilterData(BitInput &Inp);
- bool ReadFilter(BitInput &Inp,UnpackFilter &Filter);
- bool AddFilter(UnpackFilter &Filter);
- bool AddFilter();
- void InitFilters();
- ComprDataIO *UnpIO;
- BitInput Inp;
- #ifdef RAR_SMP
- void InitMT();
- bool UnpackLargeBlock(UnpackThreadData &D);
- bool ProcessDecoded(UnpackThreadData &D);
- ThreadPool *UnpThreadPool;
- UnpackThreadData *UnpThreadData;
- uint MaxUserThreads;
- byte *ReadBufMT;
- #endif
- Array<byte> FilterSrcMemory;
- Array<byte> FilterDstMemory;
- // Filters code, one entry per filter.
- Array<UnpackFilter> Filters;
- uint OldDist[4],OldDistPtr;
- uint LastLength;
- // LastDist is necessary only for RAR2 and older with circular OldDist
- // array. In RAR3 last distance is always stored in OldDist[0].
- uint LastDist;
- size_t UnpPtr,WrPtr;
-
- // Top border of read packed data.
- int ReadTop;
- // Border to call UnpReadBuf. We use it instead of (ReadTop-C)
- // for optimization reasons. Ensures that we have C bytes in buffer
- // unless we are at the end of file.
- int ReadBorder;
- UnpackBlockHeader BlockHeader;
- UnpackBlockTables BlockTables;
- size_t WriteBorder;
- byte *Window;
- FragmentedWindow FragWindow;
- bool Fragmented;
- int64 DestUnpSize;
- bool Suspended;
- bool UnpAllBuf;
- bool UnpSomeRead;
- int64 WrittenFileSize;
- bool FileExtracted;
- /***************************** Unpack v 1.5 *********************************/
- void Unpack15(bool Solid);
- void ShortLZ();
- void LongLZ();
- void HuffDecode();
- void GetFlagsBuf();
- void UnpInitData15(int Solid);
- void InitHuff();
- void CorrHuff(ushort *CharSet,byte *NumToPlace);
- void CopyString15(uint Distance,uint Length);
- uint DecodeNum(uint Num,uint StartPos,uint *DecTab,uint *PosTab);
- ushort ChSet[256],ChSetA[256],ChSetB[256],ChSetC[256];
- byte NToPl[256],NToPlB[256],NToPlC[256];
- uint FlagBuf,AvrPlc,AvrPlcB,AvrLn1,AvrLn2,AvrLn3;
- int Buf60,NumHuf,StMode,LCount,FlagsCnt;
- uint Nhfb,Nlzb,MaxDist3;
- /***************************** Unpack v 1.5 *********************************/
- /***************************** Unpack v 2.0 *********************************/
- void Unpack20(bool Solid);
- DecodeTable MD[4]; // Decode multimedia data, up to 4 channels.
- unsigned char UnpOldTable20[MC20*4];
- bool UnpAudioBlock;
- uint UnpChannels,UnpCurChannel;
- int UnpChannelDelta;
- void CopyString20(uint Length,uint Distance);
- bool ReadTables20();
- void UnpWriteBuf20();
- void UnpInitData20(int Solid);
- void ReadLastTables();
- byte DecodeAudio(int Delta);
- struct AudioVariables AudV[4];
- /***************************** Unpack v 2.0 *********************************/
- /***************************** Unpack v 3.0 *********************************/
- enum BLOCK_TYPES {BLOCK_LZ,BLOCK_PPM};
- void UnpInitData30(bool Solid);
- void Unpack29(bool Solid);
- void InitFilters30(bool Solid);
- bool ReadEndOfBlock();
- bool ReadVMCode();
- bool ReadVMCodePPM();
- bool AddVMCode(uint FirstByte,byte *Code,uint CodeSize);
- int SafePPMDecodeChar();
- bool ReadTables30();
- bool UnpReadBuf30();
- void UnpWriteBuf30();
- void ExecuteCode(VM_PreparedProgram *Prg);
- int PrevLowDist,LowDistRepCount;
- ModelPPM PPM;
- int PPMEscChar;
- byte UnpOldTable[HUFF_TABLE_SIZE30];
- int UnpBlockType;
- // If we already read decoding tables for Unpack v2,v3,v5.
- // We should not use a single variable for all algorithm versions,
- // because we can have a corrupt archive with one algorithm file
- // followed by another algorithm file with "solid" flag and we do not
- // want to reuse tables from one algorithm in another.
- bool TablesRead2,TablesRead3,TablesRead5;
- // Virtual machine to execute filters code.
- RarVM VM;
-
- // Buffer to read VM filters code. We moved it here from AddVMCode
- // function to reduce time spent in BitInput constructor.
- BitInput VMCodeInp;
- // Filters code, one entry per filter.
- Array<UnpackFilter30 *> Filters30;
- // Filters stack, several entrances of same filter are possible.
- Array<UnpackFilter30 *> PrgStack;
- // Lengths of preceding data blocks, one length of one last block
- // for every filter. Used to reduce the size required to write
- // the data block length if lengths are repeating.
- Array<int> OldFilterLengths;
- int LastFilter;
- /***************************** Unpack v 3.0 *********************************/
- public:
- Unpack(ComprDataIO *DataIO);
- ~Unpack();
- void Init(size_t WinSize,bool Solid);
- void DoUnpack(uint Method,bool Solid);
- bool IsFileExtracted() {return(FileExtracted);}
- void SetDestSize(int64 DestSize) {DestUnpSize=DestSize;FileExtracted=false;}
- void SetSuspended(bool Suspended) {Unpack::Suspended=Suspended;}
- #ifdef RAR_SMP
- void SetThreads(uint Threads);
- void UnpackDecode(UnpackThreadData &D);
- #endif
- size_t MaxWinSize;
- size_t MaxWinMask;
- uint GetChar()
- {
- if (Inp.InAddr>BitInput::MAX_SIZE-30)
- {
- UnpReadBuf();
- if (Inp.InAddr>=BitInput::MAX_SIZE) // If nothing was read.
- return 0;
- }
- return Inp.InBuf[Inp.InAddr++];
- }
- };
- #endif
|