#include "MatchFinder.h" /* memcpy must be inlined - we do not want to use RTL */ #include /*#pragma function(memcpy) void* __cdecl memcpy(void* _Dst, const void* _Src, size_t _Size) { unsigned long i; for (i = 0; i < _Size; i++) ((char*)_Dst)[i] = ((char*)_Src)[i]; return _Dst; }*/ //#pragma intrinsic(memcpy) #define kMaxValForNormalize (((unsigned)1<<31)-1) /* settings for bt4: defined HASH_ARRAY_2 defined HASH_ARRAY_3 */ //#define kHash2Size 0x400 #define kNumHashDirectBytes 0 #define kNumHashBytes 3 //#define kHash3Size 0x40000 #define kHash2Size 0x10000 #define kHashSize 0x100000 #define kHashSizeSum (kHashSize+kHash2Size) #define kHash2Offset kHashSize static unsigned _cyclicBufferPos; static unsigned _cyclicBufferSize; static unsigned _matchMaxLen; static unsigned* _hash; static unsigned _cutValue; #ifdef GENERIC_INPUT static byte* _bufferBase; static unsigned _posLimit; static bool _streamEndWasReached; static byte* _pointerToLastSafePosition; static byte* _buffer; static unsigned _blockSize; static unsigned _pos; static unsigned _keepSizeBefore; static unsigned _keepSizeAfter; static unsigned _keepSizeReserv; static unsigned _streamPos; #else #define _buffer curin #define _pos pack_pos #define _streamPos pack_length #endif #ifdef GENERIC_INPUT /* LZ Window */ static void LZInWindow_Create(unsigned keepSizeBefore,unsigned keepSizeAfter,unsigned keepSizeReserv,byte**mem) { _keepSizeBefore = keepSizeBefore; _keepSizeAfter = keepSizeAfter; _keepSizeReserv = keepSizeReserv; _blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; _bufferBase = *mem; _blockSize = (_blockSize + 3) & ~3; *mem += _blockSize; _pointerToLastSafePosition = _bufferBase + _blockSize - keepSizeAfter; } static void ReadBlock(void) { if (_streamEndWasReached) return; for (;;) { unsigned size; size = (unsigned)(_bufferBase-_buffer) + _blockSize - _streamPos; if (!size) return; if (size > pack_length - pack_pos) size = pack_length - pack_pos; memcpy(_buffer+_streamPos,curin,size); curin += size; pack_pos += size; if (size == 0) { byte* pointerToPosition; _posLimit = _streamPos; pointerToPosition = _buffer + _posLimit; if (pointerToPosition > _pointerToLastSafePosition) _posLimit = _pointerToLastSafePosition - _buffer; _streamEndWasReached = true; return; } _streamPos += size; if (_streamPos >= _pos + _keepSizeAfter) { _posLimit = _streamPos - _keepSizeAfter; return; } } } static void LZInWindow_Init(void) { _buffer = _bufferBase; _pos = 0; _streamPos = 0; _streamEndWasReached = false; ReadBlock(); } #else #define LZInWindow_Create(a,b,c,d) /* nothing */ #define LZInWindow_Init() _buffer--, _pos++, _streamPos++ #endif const byte* GetPointerToCurrentPos(void) {return _buffer+_pos;} #ifdef GENERIC_INPUT static void MoveBlock(void) { unsigned offset,numBytes; offset = _buffer-_bufferBase+_pos-_keepSizeBefore; numBytes = _buffer-_bufferBase+_streamPos-offset; // copying backwards: safe to use memcpy instead of memmove memcpy(_bufferBase,_bufferBase+offset,numBytes); _buffer -= offset; } static void LZInWindow_MovePos(void) { _pos++; if (_pos > _posLimit) { const byte* pointerToPosition = _buffer+_pos; if (pointerToPosition > _pointerToLastSafePosition) MoveBlock(); ReadBlock(); } } #else #define LZInWindow_MovePos() _pos++ #endif byte GetIndexByte(int index) {return _buffer[_pos+index];} unsigned GetMatchLen(int index,unsigned distance,unsigned limit) { const byte* pby; unsigned i; #ifdef GENERIC_INPUT if (_streamEndWasReached) if ((_pos+index)+limit > _streamPos) limit = _streamPos - (_pos+index); #else unsigned limit2 = pack_length - (pack_pos + index); if (limit > limit2) limit = limit2; #endif distance++; pby = _buffer + _pos + index; for (i=0;i>1) ^ 0xEDB88320; else r >>= 1; } crc_table[i] = r; } } static unsigned Hash(const byte* ptr, unsigned* hash2Value) { unsigned temp; temp = crc_table[ptr[0]] ^ ptr[1]; *hash2Value = *(word*)ptr; //ptr[0] + ((unsigned)ptr[1] << 8); return (temp ^ ((unsigned)ptr[2]<<8)) & (kHashSize - 1); } unsigned GetLongestMatch(unsigned* distances) { unsigned lenLimit,maxLen=0; unsigned matchMinPos; const byte* cur; unsigned hash2Value,hashValue; unsigned curMatch,curMatch2; unsigned *son,*ptr0,*ptr1; unsigned len0,len1,count; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kNumHashBytes) return 0; } matchMinPos = (_pos>_cyclicBufferSize) ? (_pos-_cyclicBufferSize) : 0; cur = _buffer+_pos; hashValue = Hash(cur,&hash2Value); curMatch = _hash[hashValue]; curMatch2 = _hash[kHash2Offset + hash2Value]; _hash[kHash2Offset + hash2Value] = _pos; distances[2] = 0xFFFFFFFF; if (curMatch2 > matchMinPos) //if (_buffer[curMatch2] == cur[0]) { distances[2] = _pos - curMatch2 - 1; maxLen = 2; } _hash[hashValue] = _pos; son = _hash + kHashSizeSum; ptr0 = son + (_cyclicBufferPos << 1) + 1; ptr1 = son + (_cyclicBufferPos << 1); distances[kNumHashBytes] = 0xFFFFFFFF; len0 = len1 = kNumHashDirectBytes; count = _cutValue; for (;;) { const byte* pb; unsigned len,delta; unsigned cyclicPos; unsigned* pair; if (curMatch <= matchMinPos || count--==0) { *ptr0 = *ptr1 = 0; break; } pb = _buffer+curMatch; len = (len0 _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; cur = _buffer+_pos; hashValue = Hash(cur,&hash2Value); _hash[kHash2Offset + hash2Value] = _pos; curMatch = _hash[hashValue]; _hash[hashValue] = _pos; son = _hash+kHashSizeSum; ptr0 = son + (_cyclicBufferPos << 1) + 1; ptr1 = son + (_cyclicBufferPos << 1); len0 = len1 = kNumHashDirectBytes; count = _cutValue; for (;;) { const byte* pb; unsigned len; unsigned delta,cyclicPos; unsigned* pair; if (curMatch <= matchMinPos || count--==0) break; pb = _buffer+curMatch; len = (len0