commit 42e04486e752ae91bba1d66fa08e7627c12243e2 Author: rgimad Date: Sat Mar 22 18:41:40 2025 +0300 get lzma_c from kerpack_linux diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84a4fc6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.exe +kpack_c +*.code-workspace diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..f87f5c1 --- /dev/null +++ b/Makefile @@ -0,0 +1 @@ +# TODO \ No newline at end of file diff --git a/lzma_c/LZMAEncoder.c b/lzma_c/LZMAEncoder.c new file mode 100644 index 0000000..bc6f7a5 --- /dev/null +++ b/lzma_c/LZMAEncoder.c @@ -0,0 +1,1078 @@ +#include "LZMAEncoder.h" +#include "MatchFinder.h" + +const byte kLiteralNextStates[kNumStates] = {0,0,0,0,1,2,3,4,5,6,4,5}; +const byte kMatchNextStates[kNumStates] = {7,7,7,7,7,7,7,10,10,10,10,10}; +const byte kRepNextStates[kNumStates] = {8,8,8,8,8,8,8,11,11,11,11,11}; +const byte kShortRepNextStates[kNumStates] = {9,9,9,9,9,9,9,11,11,11,11,11}; + +static CState _state; +static byte _previousByte; +static unsigned _repDistances[kNumRepDistances]; + +static COptimal _optimum[kNumOpts]; +static CMyBitEncoder _isMatch[kNumStates][kNumPosStatesEncodingMax]; +static CMyBitEncoder _isRep[kNumStates]; +static CMyBitEncoder _isRepG0[kNumStates]; +static CMyBitEncoder _isRepG1[kNumStates]; +static CMyBitEncoder _isRepG2[kNumStates]; +static CMyBitEncoder _isRep0Long[kNumStates][kNumPosStatesEncodingMax]; +static NRangeCoder_CBitTreeEncoder _posSlotEncoder[kNumLenToPosStates]; +static CMyBitEncoder _posEncoders[kNumFullDistances - kEndPosModelIndex]; +static NRangeCoder_CBitTreeEncoder _posAlignEncoder; +static NLength_CPriceTableEncoder _lenEncoder; +static NLength_CPriceTableEncoder _repMatchLenEncoder; +static CLiteralEncoder _literalEncoder; +static unsigned _matchDistances[kMatchMaxLen+1]; +static unsigned _numFastBytes; +static unsigned _longestMatchLength; +static unsigned _additionalOffset; +static unsigned _optimumEndIndex; +static unsigned _optimumCurrentIndex; +static bool _longestMatchWasFound; +static unsigned _posSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; +static unsigned _distancesPrices[kNumLenToPosStates][kNumFullDistances]; +static unsigned _alignPrices[kAlignTableSize]; +static unsigned _alignPriceCount; +static unsigned _distTableSize; +static unsigned _posStateBits; +static unsigned _posStateMask; +static unsigned _numLiteralPosStateBits; +static unsigned _numLiteralContextBits; +static unsigned _dictionarySize; +static uint64 lastPosSlotFillingPos; +static uint64 nowPos64; +static bool _finished; +static bool _writeEndMark; + +static byte g_FastPos[1024]; + +// must be called before work +static void FastPosInit(void) +{ + int c = 2; + int slotFast; + unsigned j,k; + g_FastPos[0] = 0; + g_FastPos[1] = 1; + for (slotFast = 2; slotFast < 20; slotFast++) + { + k = (1 << ((slotFast >> 1) - 1)); + for (j=0;j>9]+18; + return g_FastPos[pos>>18]+36; +} +static unsigned GetPosSlot2(unsigned pos) +{ + if (pos < (1<<16)) + return g_FastPos[pos>>6]+12; + if (pos < (1<<25)) + return g_FastPos[pos>>15]+30; + return g_FastPos[pos>>24]+48; +} + +unsigned pack_length; +unsigned pack_pos; +const byte* curin; +byte* curout; + +static void NLength_CEncoder_Init(NLength_CEncoder*e, unsigned numPosStates) +{ + unsigned posState; + CMyBitEncoder_Init(e->_choice); + CMyBitEncoder_Init(e->_choice2); + for (posState=0;posState_lowCoder[posState],kNumLowBits); + CBitTreeEncoder_Init(&e->_midCoder[posState],kNumMidBits); + } + CBitTreeEncoder_Init(&e->_highCoder,kNumHighBits); +} + +static void NLength_CEncoder_Encode(NLength_CEncoder*e, unsigned symbol, unsigned posState) +{ + if (symbol < kNumLowSymbols) + { + CMyBitEncoder_Encode(&e->_choice,0); + CBitTreeEncoder_Encode(&e->_lowCoder[posState],symbol); + } + else + { + CMyBitEncoder_Encode(&e->_choice,1); + if (symbol < kNumLowSymbols + kNumMidSymbols) + { + CMyBitEncoder_Encode(&e->_choice2,0); + CBitTreeEncoder_Encode(&e->_midCoder[posState],symbol-kNumLowSymbols); + } + else + { + CMyBitEncoder_Encode(&e->_choice2,1); + CBitTreeEncoder_Encode(&e->_highCoder,symbol-kNumLowSymbols-kNumMidSymbols); + } + } +} + +static unsigned NLength_CEncoder_GetPrice(NLength_CEncoder*e, unsigned symbol, unsigned posState) +{ + unsigned price; + if (symbol < kNumLowSymbols) + return CMyBitEncoder_GetPrice0(&e->_choice) + + CBitTreeEncoder_GetPrice(&e->_lowCoder[posState],symbol); + price = CMyBitEncoder_GetPrice1(&e->_choice); + if (symbol < kNumLowSymbols + kNumMidSymbols) + { + price += CMyBitEncoder_GetPrice0(&e->_choice2); + price += CBitTreeEncoder_GetPrice(&e->_midCoder[posState],symbol-kNumLowSymbols); + } + else + { + price += CMyBitEncoder_GetPrice1(&e->_choice2); + price += CBitTreeEncoder_GetPrice(&e->_highCoder,symbol-kNumLowSymbols-kNumMidSymbols); + } + return price; +} + +static void CPriceTableEncoder_SetTableSize(NLength_CPriceTableEncoder*pte,unsigned tableSize) +{pte->_tableSize = tableSize;} +static unsigned CPriceTableEncoder_GetPrice(NLength_CPriceTableEncoder*pte,unsigned symbol,unsigned posState) +{return pte->_prices[symbol][posState];} +static void CPriceTableEncoder_UpdateTable(NLength_CPriceTableEncoder*pte,unsigned posState) +{ + unsigned len; + for (len=0;len_tableSize;len++) + pte->_prices[len][posState] = NLength_CEncoder_GetPrice(&pte->base,len,posState); + pte->_counters[posState] = pte->_tableSize; +} +static void CPriceTableEncoder_UpdateTables(NLength_CPriceTableEncoder*pte,unsigned numPosStates) +{ + unsigned posState; + for (posState=0;posStatebase,symbol,posState); + if (--pte->_counters[posState] == 0) + CPriceTableEncoder_UpdateTable(pte,posState); +} + +static void CBaseState_Init(void) +{ + unsigned i; + CState_Init(_state); + _previousByte = 0; + for (i=0;i> i) & 1; + CMyBitEncoder_Encode(&le[context],bit); + context = (context << 1) | bit; + } +} + +static void CLiteralEncoder2_EncodeMatched(CLiteralEncoder2 le, byte matchByte, byte symbol) +{ + unsigned context = 1; + int i; + unsigned bit,matchBit; + for (i=8;i--;) + { + bit = (symbol >> i) & 1; + matchBit = (matchByte >> i) & 1; + CMyBitEncoder_Encode(&le[0x100 + (matchBit<<8) + context],bit); + context = (context << 1) | bit; + if (matchBit != bit) + { + while (i--) + { + bit = (symbol >> i) & 1; + CMyBitEncoder_Encode(&le[context],bit); + context = (context << 1) | bit; + } + break; + } + } +} + +static unsigned CLiteralEncoder2_GetPrice(CLiteralEncoder2 le, bool matchMode, byte matchByte, byte symbol) +{ + unsigned price = 0; + unsigned context = 1; + unsigned bit,matchBit; + int i = 8; + if (matchMode) + { + do + { + i--; + matchBit = (matchByte >> i) & 1; + bit = (symbol >> i) & 1; + price += CMyBitEncoder_GetPrice(&le[0x100 + (matchBit<<8) + context],bit); + context = (context << 1) | bit; + if (matchBit != bit) + break; + } while (i); + } + while (i--) + { + bit = (symbol >> i) & 1; + price += CMyBitEncoder_GetPrice(&le[context],bit); + context = (context << 1) | bit; + } + return price; +} + +static void WriteEndMarker(unsigned posState) +{ + unsigned posSlot; + if (!_writeEndMark) + return; + CMyBitEncoder_Encode(&_isMatch[_state][posState],1); + CMyBitEncoder_Encode(&_isRep[_state],0); + CState_UpdateMatch(_state); + CPriceTableEncoder_Encode(&_lenEncoder,0,posState); + posSlot = (1<>kNumAlignBits,30-kNumAlignBits); + CBitTreeEncoder_ReverseEncode(&_posAlignEncoder,((1<<30)-1) & kAlignMask); +} + +static void CEncoder_Flush(void) +{ + WriteEndMarker((unsigned)nowPos64 & _posStateMask); + RangeEncoder_FlushData(); +} + +static void CLiteralEncoder_Create(CLiteralEncoder*le, byte** memory, int numPosBits, int numPrevBits) +{ + unsigned numStates; + le->_coders = (CLiteralEncoder2*)*memory; + numStates = 1 << (numPosBits+numPrevBits); + *memory = (byte*)(le->_coders + numStates); + le->_numPosBits = numPosBits; + le->_posMask = (1<_numPrevBits = numPrevBits; +} + +static void CLiteralEncoder_Init(CLiteralEncoder*le) +{ + unsigned numStates,i; + numStates = 1 << (le->_numPosBits + le->_numPrevBits); + for (i=0;i_coders[i]); +} + +static unsigned CLiteralEncoder_GetState(CLiteralEncoder*le,unsigned pos,byte prevByte) +{return ((pos&le->_posMask)<_numPrevBits)+(prevByte>>(8-le->_numPrevBits));} +static CLiteralEncoder2* CLiteralEncoder_GetSubCoder(CLiteralEncoder*le,unsigned pos,byte prevByte) +{return &le->_coders[CLiteralEncoder_GetState(le,pos,prevByte)];} + +static unsigned CLiteralEncoder_GetPrice(CLiteralEncoder*le,unsigned pos,byte prevByte, + bool matchMode, byte matchByte, byte symbol) +{ + return CLiteralEncoder2_GetPrice(le->_coders[CLiteralEncoder_GetState(le,pos,prevByte)], + matchMode, matchByte, symbol); +} + +static void CEncoder_Create(void*workmem) +{ + byte* workpos = (byte*)workmem; + /* align on dword boundary */ + unsigned a; + a = (unsigned)workpos & 3; + if (a) workpos += 4-a; + /* sizeof(CLiteralEncoder2) * (1<<(numPosBits+numPrevBits)) for literal encoders */ + /* = 0xC00 * 8 = 0x6000 with current settings */ + CLiteralEncoder_Create(&_literalEncoder,&workpos,_numLiteralPosStateBits,_numLiteralContextBits); + /* (dictsize+0x1223)*1.5+256 for LZ input window */ + /* (0x140400 + (dictsize+1)*2) * 4 for match finder hash */ + MatchFinder_Create(_dictionarySize,kNumOpts,_numFastBytes, + kMatchMaxLen*2+1-_numFastBytes,&workpos); + /* total 0x508C3C + dictsize*9.5 */ + /* plus max 6 bytes for alignment */ +} + +static void CEncoder_Init(void) +{ + int i; + unsigned j; + CBaseState_Init(); + RangeEncoder_Init(); + for (i=0;i>1)-1-kNumAlignBits)<>1)-1); + base = (2|(posSlot&1))<=0x80) + return kIfinityPrice; + lenToPosState = GetLenToPosState(len); + if (pos < kNumFullDistances) + price = _distancesPrices[lenToPosState][pos]; + else + price = _posSlotPrices[lenToPosState][GetPosSlot2(pos)] + + _alignPrices[pos & kAlignMask]; + return price + CPriceTableEncoder_GetPrice(&_lenEncoder,len-kMatchMinLen,posState); +} + +static void GetOptimum(unsigned position,unsigned*backRes,unsigned*lenRes) +{ + int lenMain,lenEnd; + COptimal* opt,*prevOpt; + int reps[kNumRepDistances]; + int repLens[kNumRepDistances]; + int repIndex,repMaxIndex; + int i,len,repLen,lenTest,newLen,lenTestTemp,lenTest2; + int posState,posStateNext; + byte currentByte,matchByte; + unsigned matchPrice,repMatchPrice,shortRepPrice,normalMatchPrice,curAndLenPrice,curPrice,curAnd1Price,curAndLenCharPrice; + unsigned nextMatchPrice,nextRepMatchPrice; + int cur,posPrev,pos; + CState state,state2; + const byte* data; + bool nextIsChar; + int numAvailableBytesFull,numAvailableBytes; + int backOffset,offset; + int limit; + if (_optimumEndIndex != _optimumCurrentIndex) + { + opt = &_optimum[_optimumCurrentIndex]; + *lenRes = opt->PosPrev - _optimumCurrentIndex; + *backRes = opt->BackPrev; + _optimumCurrentIndex = opt->PosPrev; + return; + } + _optimumCurrentIndex = _optimumEndIndex = 0; + if (!_longestMatchWasFound) + lenMain = ReadMatchDistances(); + else + { + lenMain = _longestMatchLength; + _longestMatchWasFound = false; + } + for (i=0;i repLens[repMaxIndex]) + repMaxIndex = i; + } + if (repLens[repMaxIndex] >= _numFastBytes) + { + *backRes = repMaxIndex; + *lenRes = repLens[repMaxIndex]; + MovePos(*lenRes-1); + return; + } + if (lenMain >= _numFastBytes) + { + *backRes = _matchDistances[_numFastBytes]+kNumRepDistances; + *lenRes = lenMain; + MovePos(lenMain-1); + return; + } + currentByte = GetIndexByte(0-1); + _optimum[0].State = _state; + matchByte = GetIndexByte(0-_repDistances[0]-2); + posState = position & _posStateMask; + _optimum[1].Price = CMyBitEncoder_GetPrice0(&_isMatch[_state][posState]) + + CLiteralEncoder_GetPrice(&_literalEncoder,position,_previousByte, + (bool)!CState_IsCharState(_state),matchByte,currentByte); + COptimal_MakeAsChar(&_optimum[1]); + _optimum[1].PosPrev = 0; + for (i=0;iPrice) + { + opt->Price = curAndLenPrice; + opt->PosPrev = 0; + opt->BackPrev = i; + opt->Prev1IsChar = false; + } + } + } + cur=0; + lenEnd = lenMain; + while (1) + { + cur++; + if (cur==lenEnd) + { + *lenRes = Backward(backRes,cur); + return; + } + position++; + opt = &_optimum[cur]; + posPrev = opt->PosPrev; + if (opt->Prev1IsChar) + { + posPrev--; + if (opt->Prev2) + { + state = _optimum[opt->PosPrev2].State; + if (opt->BackPrev2 < kNumRepDistances) + CState_UpdateRep(state); + else + CState_UpdateMatch(state); + } + else + state = _optimum[posPrev].State; + CState_UpdateChar(state); + } + else + state = _optimum[posPrev].State; + if (posPrev == cur-1) + { + if (COptimal_IsShortRep(opt)) + CState_UpdateShortRep(state); + else + CState_UpdateChar(state); + } + else + { + if (opt->Prev1IsChar && opt->Prev2) + { + posPrev = opt->PosPrev2; + pos = opt->BackPrev2; + CState_UpdateRep(state); + } + else + { + pos = opt->BackPrev; + if (pos < kNumRepDistances) + CState_UpdateRep(state); + else + CState_UpdateMatch(state); + } + prevOpt = &_optimum[posPrev]; + if (pos < kNumRepDistances) + { + reps[0] = prevOpt->Backs[pos]; + for (i=1;i<=pos;i++) + reps[i] = prevOpt->Backs[i-1]; + for (;iBacks[i]; + } + else + { + reps[0] = pos-kNumRepDistances; + for (i=1;iBacks[i-1]; + } + } + opt->State = state; + for (i=0;iBacks[i] = reps[i]; + newLen = ReadMatchDistances(); + if (newLen >= _numFastBytes) + { + _longestMatchLength = newLen; + _longestMatchWasFound = true; + *lenRes = Backward(backRes,cur); + return; + } + curPrice = opt->Price; + data = GetPointerToCurrentPos()-1; + currentByte = *data; + matchByte = data[-1-reps[0]]; + posState = position & _posStateMask; + curAnd1Price = curPrice + CMyBitEncoder_GetPrice0(&_isMatch[state][posState]) + + CLiteralEncoder_GetPrice(&_literalEncoder,position,data[-1],(bool)!CState_IsCharState(state),matchByte,currentByte); + opt = &_optimum[cur+1]; + nextIsChar = false; + if (curAnd1Price < opt->Price) + { + opt->Price = curAnd1Price; + opt->PosPrev = cur; + COptimal_MakeAsChar(opt); + nextIsChar = true; + } + matchPrice = curPrice + CMyBitEncoder_GetPrice1(&_isMatch[state][posState]); + repMatchPrice = matchPrice + CMyBitEncoder_GetPrice1(&_isRep[state]); + if (matchByte == currentByte && !(opt->PosPrevBackPrev)) + { + shortRepPrice = repMatchPrice + GetRepLen1Price(state,posState); + if (shortRepPrice <= opt->Price) + { + opt->Price = shortRepPrice; + opt->PosPrev = cur; + COptimal_MakeAsShortRep(opt); + } + } + numAvailableBytesFull = GetNumAvailableBytes()+1; + if (numAvailableBytesFull > kNumOpts-1-cur) + numAvailableBytesFull = kNumOpts-1-cur; + numAvailableBytes = numAvailableBytesFull; + if (numAvailableBytes < 2) + continue; + if (numAvailableBytes > _numFastBytes) + numAvailableBytes = _numFastBytes; + if (numAvailableBytes >= 3 && !nextIsChar) + { + // try Literal + rep0 + int temp; + backOffset = reps[0]+1; + for (temp=1;temp=2) + { + int posStateNext; + unsigned nextRepMatchPrice; + state2 = state; + CState_UpdateChar(state2); + posStateNext = (position+1) & _posStateMask; + nextRepMatchPrice = curAnd1Price + + CMyBitEncoder_GetPrice1(&_isMatch[state2][posStateNext]) + + CMyBitEncoder_GetPrice1(&_isRep[state2]); + while (lenEnd < cur+1+lenTest) + _optimum[++lenEnd].Price = kIfinityPrice; + curAndLenPrice = nextRepMatchPrice + GetRepPrice(0,lenTest,state2,posStateNext); + opt = &_optimum[cur+1+lenTest]; + if (curAndLenPrice < opt->Price) + { + opt->Price = curAndLenPrice; + opt->PosPrev = cur+1; + opt->BackPrev = 0; + opt->Prev1IsChar = true; + opt->Prev2 = false; + } + } + } + for (repIndex=0;repIndexPrice) + { + opt->Price = curAndLenPrice; + opt->PosPrev = cur; + opt->BackPrev = repIndex; + opt->Prev1IsChar = false; + } + } while (--lenTest>=2); + lenTest = lenTestTemp; + lenTest2 = lenTest+1; + limit = lenTest2 + _numFastBytes; + if (limit > numAvailableBytesFull) + limit = numAvailableBytesFull; + for (;lenTest2= 2) + { + unsigned nextMatchPrice,nextRepMatchPrice; + int offset; + state2 = state; + CState_UpdateRep(state2); + posStateNext = (position+lenTest)&_posStateMask; + curAndLenCharPrice = repMatchPrice + GetRepPrice(repIndex,lenTest,state,posState) + + CMyBitEncoder_GetPrice0(&_isMatch[state2][posStateNext]) + + CLiteralEncoder_GetPrice(&_literalEncoder,position+lenTest,data[lenTest-1],true,data[lenTest-backOffset],data[lenTest]); + CState_UpdateChar(state2); + posStateNext = (position+lenTest+1)&_posStateMask; + nextMatchPrice = curAndLenCharPrice + CMyBitEncoder_GetPrice1(&_isMatch[state2][posStateNext]); + nextRepMatchPrice = nextMatchPrice + CMyBitEncoder_GetPrice1(&_isRep[state2]); + offset = lenTest+1+lenTest2; + while (lenEndPrice) + { + opt->Price = curAndLenPrice; + opt->PosPrev = cur+lenTest+1; + opt->BackPrev = 0; + opt->Prev1IsChar = true; + opt->Prev2 = true; + opt->PosPrev2 = cur; + opt->BackPrev2 = repIndex; + } + } + } + if (newLen > numAvailableBytes) + newLen = numAvailableBytes; + if (newLen >= 2) + { + if (newLen==2 && _matchDistances[2] >= 0x80) + continue; + normalMatchPrice = matchPrice + CMyBitEncoder_GetPrice0(&_isRep[state]); + while (lenEnd < cur+newLen) + _optimum[++lenEnd].Price = kIfinityPrice; + for (lenTest=newLen;lenTest>=2;lenTest--) + { + backOffset = _matchDistances[lenTest]; + curAndLenPrice = normalMatchPrice + GetPosLenPrice(backOffset,lenTest,posState); + opt = &_optimum[cur+lenTest]; + if (curAndLenPrice < opt->Price) + { + opt->Price = curAndLenPrice; + opt->PosPrev = cur; + opt->BackPrev = backOffset+kNumRepDistances; + opt->Prev1IsChar = false; + } + if (lenTest==newLen || backOffset!=_matchDistances[lenTest+1]) + { + // Try Match + Literal + Rep0 + backOffset++; + lenTest2 = lenTest+1; + limit = lenTest2+_numFastBytes; + if (limit > numAvailableBytesFull) + limit = numAvailableBytesFull; + for (;lenTest2= 2) + { + state2 = state; + CState_UpdateMatch(state2); + posStateNext = (position+lenTest)&_posStateMask; + curAndLenCharPrice = curAndLenPrice + CMyBitEncoder_GetPrice0(&_isMatch[state2][posStateNext]) + + CLiteralEncoder_GetPrice(&_literalEncoder,position+lenTest,data[lenTest-1],true,data[lenTest-backOffset],data[lenTest]); + CState_UpdateChar(state2); + posStateNext = (position+lenTest+1)&_posStateMask; + nextMatchPrice = curAndLenCharPrice + CMyBitEncoder_GetPrice1(&_isMatch[state2][posStateNext]); + nextRepMatchPrice = nextMatchPrice + CMyBitEncoder_GetPrice1(&_isRep[state2]); + offset = lenTest+1+lenTest2; + while (lenEndPrice) + { + opt->Price = curAndLenPrice; + opt->PosPrev = cur+lenTest+1; + opt->BackPrev = 0; + opt->Prev1IsChar = true; + opt->Prev2 = true; + opt->PosPrev2 = cur; + opt->BackPrev2 = backOffset - 1 + kNumRepDistances; + } + } + } + } + } + } +} + +static bool CodeOneBlock(void) +{ + unsigned posState; + byte curByte,matchByte; + unsigned pos,len,distance,i; + unsigned posSlot,lenToPosState; + CLiteralEncoder2* subCoder; + uint64 progressPosValuePrev; + + if (_finished) + return false; + _finished = true; + progressPosValuePrev = nowPos64; + if (nowPos64 == 0) + { + if (GetNumAvailableBytes() == 0) + { + CEncoder_Flush(); + return false; + } + ReadMatchDistances(); + posState = (unsigned)nowPos64 & _posStateMask; + CMyBitEncoder_Encode(&_isMatch[_state][posState],0); + CState_UpdateChar(_state); + curByte = GetIndexByte(0 - _additionalOffset); + CLiteralEncoder2_Encode( + *CLiteralEncoder_GetSubCoder(&_literalEncoder,(unsigned)nowPos64,_previousByte), + curByte); + _previousByte = curByte; + _additionalOffset--; + nowPos64++; + } + if (GetNumAvailableBytes() == 0) + { + CEncoder_Flush(); + return false; + } + for (;;) + { + posState = (unsigned)nowPos64 & _posStateMask; + GetOptimum((unsigned)nowPos64,&pos,&len); + if (len==1 && pos==0xFFFFFFFF) + { + CMyBitEncoder_Encode(&_isMatch[_state][posState],0); + curByte = GetIndexByte(0-_additionalOffset); + subCoder = CLiteralEncoder_GetSubCoder(&_literalEncoder,(unsigned)nowPos64, + _previousByte); + if (!CState_IsCharState(_state)) + { + matchByte = GetIndexByte(0-_repDistances[0]-1-_additionalOffset); + CLiteralEncoder2_EncodeMatched(*subCoder,matchByte,curByte); + } + else + CLiteralEncoder2_Encode(*subCoder,curByte); + CState_UpdateChar(_state); + _previousByte = curByte; + } + else + { + CMyBitEncoder_Encode(&_isMatch[_state][posState],1); + if (pos < kNumRepDistances) + { + CMyBitEncoder_Encode(&_isRep[_state],1); + if (pos==0) + { + CMyBitEncoder_Encode(&_isRepG0[_state],0); + CMyBitEncoder_Encode(&_isRep0Long[_state][posState], + (len==1) ? 0 : 1); + } + else + { + CMyBitEncoder_Encode(&_isRepG0[_state],1); + if (pos==1) + CMyBitEncoder_Encode(&_isRepG1[_state],0); + else + { + CMyBitEncoder_Encode(&_isRepG1[_state],1); + CMyBitEncoder_Encode(&_isRepG2[_state],pos-2); + } + } + if (len==1) + CState_UpdateShortRep(_state); + else + { + CPriceTableEncoder_Encode(&_repMatchLenEncoder,len-kMatchMinLen,posState); + CState_UpdateRep(_state); + } + distance = _repDistances[pos]; + if (pos) + { + for (i=pos;i;i--) + _repDistances[i] = _repDistances[i-1]; + _repDistances[0] = distance; + } + } + else + { + CMyBitEncoder_Encode(&_isRep[_state],0); + CState_UpdateMatch(_state); + CPriceTableEncoder_Encode(&_lenEncoder,len-kMatchMinLen,posState); + pos -= kNumRepDistances; + posSlot = GetPosSlot(pos); + lenToPosState = GetLenToPosState(len); + CBitTreeEncoder_Encode(&_posSlotEncoder[lenToPosState],posSlot); + if (posSlot >= kStartPosModelIndex) + { + unsigned footerBits; + unsigned base,posReduced; + footerBits = (posSlot>>1)-1; + base = (2 | (posSlot&1)) << footerBits; + posReduced = pos-base; + if (posSlot < kEndPosModelIndex) + ReverseBitTreeEncode(_posEncoders+base-posSlot-1, + footerBits,posReduced); + else + { + RangeEncoder_EncodeDirectBits(posReduced>>kNumAlignBits,footerBits-kNumAlignBits); + CBitTreeEncoder_ReverseEncode(&_posAlignEncoder,posReduced&kAlignMask); + if (--_alignPriceCount == 0) + FillAlignPrices(); + } + } + distance = pos; + for (i=kNumRepDistances-1;i;i--) + _repDistances[i] = _repDistances[i-1]; + _repDistances[0] = distance; + } + _previousByte = GetIndexByte(len-1-_additionalOffset); + } + _additionalOffset -= len; + nowPos64 += len; + if (nowPos64 - lastPosSlotFillingPos >= (1<<9)) + { + FillPosSlotPrices(); + FillDistancesPrices(); + lastPosSlotFillingPos = nowPos64; + } + if (!_additionalOffset) + { + if (GetNumAvailableBytes() == 0) + { + CEncoder_Flush(); + return false; + } + if (nowPos64 - progressPosValuePrev >= (1<<12)) + { + _finished = false; + return true; + } + } + } +} + +extern void __stdcall lzma_set_dict_size( + unsigned logdictsize) +{ + _dictionarySize = 1 << logdictsize; + _distTableSize = logdictsize*2; +} + +extern unsigned __stdcall lzma_compress( + const void* source, + void* destination, + unsigned length, + void* workmem) +{ + FastPosInit(); + //memset(&encoder,0,sizeof(encoder)); + //memset(&rangeEncoder,0,sizeof(rangeEncoder)); + // CEncoder::CEncoder, CEncoder::SetCoderProperties + _numFastBytes = 128; +#ifdef FOR_KERPACK + _posStateBits = 0; + _posStateMask = 0; +#else + _posStateBits = 2; + _posStateMask = 3; +#endif + _numLiteralContextBits = 3; + _numLiteralPosStateBits = 0; + _writeEndMark = false; + // CEncoder::Code - поехали! + _finished = false; + CEncoder_Create(workmem); + CEncoder_Init(); + FillPosSlotPrices(); + FillDistancesPrices(); + FillAlignPrices(); + CPriceTableEncoder_SetTableSize(&_lenEncoder,_numFastBytes+1-kMatchMinLen); + CPriceTableEncoder_UpdateTables(&_lenEncoder,1<<_posStateBits); + CPriceTableEncoder_SetTableSize(&_repMatchLenEncoder,_numFastBytes+1-kMatchMinLen); + CPriceTableEncoder_UpdateTables(&_repMatchLenEncoder,1<<_posStateBits); + lastPosSlotFillingPos = 0; + nowPos64 = 0; + pack_length = length; + pack_pos = 0; + curin = (const byte*)source; + curout = (byte*)destination; + MatchFinder_Init(); + while (CodeOneBlock()) ; + return curout - (byte*)destination; +} diff --git a/lzma_c/LZMAEncoder.h b/lzma_c/LZMAEncoder.h new file mode 100644 index 0000000..d9bfbe4 --- /dev/null +++ b/lzma_c/LZMAEncoder.h @@ -0,0 +1,53 @@ +#ifndef _LZMA_ENCODER_H +#define _LZMA_ENCODER_H + +#include "lzma.h" +#include "RangeCoderBitTree.h" + +typedef struct +{ + CState State; + bool Prev1IsChar; + bool Prev2; + unsigned PosPrev2; + unsigned BackPrev2; + unsigned Price; + unsigned PosPrev; + unsigned BackPrev; + unsigned Backs[kNumRepDistances]; +} COptimal; +#define COptimal_MakeAsChar(a) (a)->BackPrev=(unsigned)-1,(a)->Prev1IsChar=false +#define COptimal_MakeAsShortRep(a) (a)->BackPrev=0,(a)->Prev1IsChar=false +#define COptimal_IsShortRep(a) ((a)->BackPrev==0) + +#define kIfinityPrice 0xFFFFFFF +#define kNumOpts (1<<12) + +typedef CMyBitEncoder CLiteralEncoder2[0x300]; +typedef struct +{ + CLiteralEncoder2* _coders; + int _numPrevBits; + int _numPosBits; + unsigned _posMask; +} CLiteralEncoder; + +typedef struct +{ + CMyBitEncoder _choice; + CMyBitEncoder _choice2; + NRangeCoder_CBitTreeEncoder _lowCoder[kNumPosStatesEncodingMax]; + NRangeCoder_CBitTreeEncoder _midCoder[kNumPosStatesEncodingMax]; + NRangeCoder_CBitTreeEncoder _highCoder; +} NLength_CEncoder; + +typedef struct +{ + NLength_CEncoder base; + unsigned _prices[kNumSymbolsTotal][kNumPosStatesEncodingMax]; + unsigned _tableSize; + unsigned _counters[kNumPosStatesEncodingMax]; +} NLength_CPriceTableEncoder; +#define CPriceTableEncoder_Init(a,b) NLength_CEncoder_Init(&a.base,b) + +#endif diff --git a/lzma_c/LZMAEncoderApi.h b/lzma_c/LZMAEncoderApi.h new file mode 100644 index 0000000..77cfd0b --- /dev/null +++ b/lzma_c/LZMAEncoderApi.h @@ -0,0 +1,14 @@ +#ifndef LZMA_ENCODER_API_H_ +#define LZMA_ENCODER_API_H_ + +void __stdcall lzma_set_dict_size(unsigned logdictsize); + +unsigned __stdcall lzma_compress( + const void* source, + void* destination, + unsigned length, + void* workmem, + int is_kerpack +); + +#endif \ No newline at end of file diff --git a/lzma_c/MatchFinder.c b/lzma_c/MatchFinder.c new file mode 100644 index 0000000..43622cf --- /dev/null +++ b/lzma_c/MatchFinder.c @@ -0,0 +1,422 @@ +#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> kNumMoveReducingBits]; + +void RangeEncoder_Init(void) +{ + int i; + unsigned start,end,j; + low = 0; + range = 0xFFFFFFFF; + _cacheSize = 1; + _cache = 0; + /* init price table */ +#define kNumBits (kNumBitModelTotalBits - kNumMoveReducingBits) + for (i=kNumBits;i--;) + { + start = 1 << (kNumBits - i - 1); + end = 1 << (kNumBits - i); + for (j=start;j> (kNumBits - i - 1)); + } +#undef kNumBits +} + +void RangeEncoder_ShiftLow(void) +{ + if ((unsigned)low < 0xFF000000U || (int)(low>>32)) + { + byte temp = _cache; + do + { + *curout++ = (byte)(temp + (byte)(low>>32)); + temp = 0xFF; + } while (--_cacheSize); + _cache = (byte)((unsigned)low>>24); + } + _cacheSize++; + low = (unsigned)low << 8; +} + +void RangeEncoder_FlushData(void) +{ + int i; + for (i=0;i<5;i++) + RangeEncoder_ShiftLow(); +} + +void RangeEncoder_EncodeDirectBits(unsigned value,int numTotalBits) +{ + int i; + for (i=numTotalBits;i--;) + { + range >>= 1; + if (((value >> i) & 1) == 1) + low += range; + if (range < kTopValue) + { + range <<= 8; + RangeEncoder_ShiftLow(); + } + } +} + +void CMyBitEncoder_Encode(CMyBitEncoder* e,unsigned symbol) +{ + unsigned newBound; + newBound = (range >> kNumBitModelTotalBits) * *e; + if (symbol == 0) + { + range = newBound; + *e += (kBitModelTotal - *e) >> kNumMoveBits; + } + else + { + low += newBound; + range -= newBound; + *e -= *e >> kNumMoveBits; + } + if (range < kTopValue) + { + range <<= 8; + RangeEncoder_ShiftLow(); + } +} + +unsigned CMyBitEncoder_GetPrice(CMyBitEncoder* e, unsigned symbol) +{ + return PriceTable[(((*e-symbol)^((-(int)symbol))) & (kBitModelTotal-1)) >> kNumMoveReducingBits]; +} +unsigned CMyBitEncoder_GetPrice0(CMyBitEncoder* e) +{ + return PriceTable[*e >> kNumMoveReducingBits]; +} +unsigned CMyBitEncoder_GetPrice1(CMyBitEncoder* e) +{ + return PriceTable[(kBitModelTotal - *e) >> kNumMoveReducingBits]; +} + +void CBitTreeEncoder_Init(NRangeCoder_CBitTreeEncoder*e,int numBitLevels) +{ + unsigned i; + e->numBitLevels = numBitLevels; + for (i=1;i<((unsigned)1<Models[i]); +} +void CBitTreeEncoder_Encode(NRangeCoder_CBitTreeEncoder*e,unsigned symbol) +{ + unsigned modelIndex = 1; + int bitIndex; + unsigned bit; + for (bitIndex = e->numBitLevels; bitIndex--;) + { + bit = (symbol >> bitIndex) & 1; + CMyBitEncoder_Encode(&e->Models[modelIndex],bit); + modelIndex = (modelIndex << 1) | bit; + } +} +void CBitTreeEncoder_ReverseEncode(NRangeCoder_CBitTreeEncoder*e,unsigned symbol) +{ + unsigned modelIndex = 1; + int i; + unsigned bit; + for (i=0;inumBitLevels;i++) + { + bit = symbol & 1; + CMyBitEncoder_Encode(&e->Models[modelIndex],bit); + modelIndex = (modelIndex << 1) | bit; + symbol >>= 1; + } +} +unsigned CBitTreeEncoder_GetPrice(NRangeCoder_CBitTreeEncoder*e,unsigned symbol) +{ + unsigned price = 0; + symbol |= (1 << e->numBitLevels); + while (symbol != 1) + { + price += CMyBitEncoder_GetPrice(&e->Models[symbol>>1],symbol&1); + symbol >>= 1; + } + return price; +} +unsigned CBitTreeEncoder_ReverseGetPrice(NRangeCoder_CBitTreeEncoder*e,unsigned symbol) +{ + unsigned price=0; + unsigned modelIndex=1; + int i; + unsigned bit; + for (i=e->numBitLevels;i;i--) + { + bit = symbol&1; + symbol >>= 1; + price += CMyBitEncoder_GetPrice(&e->Models[modelIndex],bit); + modelIndex = (modelIndex<<1)|bit; + } + return price; +} +unsigned ReverseBitTreeGetPrice(CMyBitEncoder*Models,unsigned NumBitLevels,unsigned symbol) +{ + unsigned price=0; + unsigned modelIndex=1; + unsigned bit; + int i; + for (i=NumBitLevels;i;i--) + { + bit = symbol & 1; + symbol >>= 1; + price += CMyBitEncoder_GetPrice(Models+modelIndex,bit); + modelIndex = (modelIndex<<1)|bit; + } + return price; +} +void ReverseBitTreeEncode(CMyBitEncoder*Models,int NumBitLevels,unsigned symbol) +{ + unsigned modelIndex = 1; + int i; + unsigned bit; + for (i=0;i>= 1; + } +} diff --git a/lzma_c/RangeCoder.h b/lzma_c/RangeCoder.h new file mode 100644 index 0000000..958a427 --- /dev/null +++ b/lzma_c/RangeCoder.h @@ -0,0 +1,7 @@ +#include "common.h" +#define kNumTopBits 24 +#define kTopValue (1< +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=lzmapack - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "lzmapack.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "lzmapack.mak" CFG="lzmapack - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "lzmapack - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "lzmapack - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "lzmapack - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O1 /Ob1 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /Zl /FD /c +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "lzmapack - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ENDIF + +# Begin Target + +# Name "lzmapack - Win32 Release" +# Name "lzmapack - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\LZMAEncoder.c +# End Source File +# Begin Source File + +SOURCE=.\MatchFinder.c +# End Source File +# Begin Source File + +SOURCE=.\RangeCoder.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\common.h +# End Source File +# Begin Source File + +SOURCE=.\lzma.h +# End Source File +# Begin Source File + +SOURCE=.\LZMAEncoder.h +# End Source File +# Begin Source File + +SOURCE=.\MatchFinder.h +# End Source File +# Begin Source File + +SOURCE=.\RangeCoder.h +# End Source File +# Begin Source File + +SOURCE=.\RangeCoderBit.h +# End Source File +# Begin Source File + +SOURCE=.\RangeCoderBitTree.h +# End Source File +# End Group +# End Target +# End Project diff --git a/lzma_c/lzmapack.dsw b/lzma_c/lzmapack.dsw new file mode 100644 index 0000000..5887eda --- /dev/null +++ b/lzma_c/lzmapack.dsw @@ -0,0 +1,44 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "lzmapack"=.\lzmapack.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "lzmatest"=.\lzmatest\lzmatest.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name lzmapack + End Project Dependency +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/lzma_c/lzmatest/lzmatest.dsp b/lzma_c/lzmatest/lzmatest.dsp new file mode 100644 index 0000000..8ad6283 --- /dev/null +++ b/lzma_c/lzmatest/lzmatest.dsp @@ -0,0 +1,102 @@ +# Microsoft Developer Studio Project File - Name="lzmatest" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=lzmatest - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "lzmatest.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "lzmatest.mak" CFG="lzmatest - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "lzmatest - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "lzmatest - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "lzmatest - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib ..\lzmapack.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "lzmatest - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib ..\lzmapack.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "lzmatest - Win32 Release" +# Name "lzmatest - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\main.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/lzma_c/lzmatest/main.cpp b/lzma_c/lzmatest/main.cpp new file mode 100644 index 0000000..4177026 --- /dev/null +++ b/lzma_c/lzmatest/main.cpp @@ -0,0 +1,31 @@ +#include +#include +extern "C" __stdcall lzma_set_dict_size(unsigned logdictsize); +extern "C" __stdcall lzma_compress( + const void* source, + void* destination, + unsigned length, + void* workmem); + +int main() +{ + FILE* f; + f = fopen("test.in","rb"); + fseek(f,0,SEEK_END); + unsigned inlen = ftell(f); + fseek(f,0,SEEK_SET); + void* in = VirtualAlloc(NULL,inlen,MEM_COMMIT,PAGE_READWRITE); + void* out = VirtualAlloc(NULL,inlen,MEM_COMMIT,PAGE_READWRITE); + fread(in,1,inlen,f); + fclose(f); + unsigned logdictsize,dictsize; + for (logdictsize=0,dictsize=1;dictsize %d\n",inlen,outlen); + f = fopen("test.out","wb"); + fwrite(out,1,outlen,f); + fclose(f); + return 0; +} diff --git a/lzma_c/readme.txt b/lzma_c/readme.txt new file mode 100644 index 0000000..5bd869f --- /dev/null +++ b/lzma_c/readme.txt @@ -0,0 +1,44 @@ +В этом каталоге находится упрощенная переписанная на C мною, diamond'ом, версия +LZMA-упаковщика. Оригинальный LZMA SDK 4.32 является copyright (c) 1999-2005 +Igor Pavlov, может быть получен на странице http://www.7-zip.org/sdk.html, +содержит, в частности, версии исходного кода на C++,C# и Java для упаковки и +распаковки, код LZMA-распаковки на ANSI-C, описание формата 7z. + +Эта версия не является безопасной в многопоточной среде, поддерживает только +bt4 match-finder, некоторые параметры упаковки зафиксированы (впрочем, это при +необходимости легко модифицировать), поддерживается только сжатие данных в +оперативной памяти. (Этих ограничений нет в оригинальном LZMA +SDK.) Эта версия не обязана компилироваться любым компилятором, ибо я использую +только VC++, хотя единственное известное мне отклонение от ANSI C состоит в +использовании VC-специфичной директивы #pragma intrinsic(memcpy), необходимой, +чтобы memcpy была встроена прямо в код - в результате библиотека не ссылается +ни на одну из функций C run-time library. (Мне это необходимо, поскольку +библиотека используется в ассемблерной программе MtApPack, не использующей +RTL и к тому же существующей и для Windows, и для Kolibri.) + +Эта библиотека, как и оригинальный LZMA SDK, может быть использована в других +программах в соответствии с одной из лицензий (на ваш выбор) GNU LGPL или +GNU CPL. (Оригинальный SDK также допускает использование оригинальной +библиотеки без ограничений при условии использования объектных файлов без +модификации кода, на данную версию это не распространяется.) + +Экспортируются две функции: в C++-стиле объявление выглядит так: +extern "C" __stdcall void lzma_set_dict_size(unsigned logdictsize); +extern "C" __stdcall unsigned lzma_compress( + const void* source, + void* destination, + unsigned length, + void* workmem); + +Перед упаковкой требуется установить размер словаря первой из этих функций, +принимающей логарифм по основанию 2 этого значения +(т.е. dictsize == (1<