Initial community commit
This commit is contained in:
parent
537bcbc862
commit
fc06254474
16440 changed files with 4239995 additions and 2 deletions
404
Src/external_dependencies/openmpt-trunk/include/unrar/unpack.hpp
vendored
Normal file
404
Src/external_dependencies/openmpt-trunk/include/unrar/unpack.hpp
vendored
Normal file
|
@ -0,0 +1,404 @@
|
|||
#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
|
Loading…
Add table
Add a link
Reference in a new issue