📄 lzmaenc.c
字号:
UInt32 backMem = p->opt[cur].backPrev;
p->optimumEndIndex = cur;
do
{
if (p->opt[cur].prev1IsChar)
{
MakeAsChar(&p->opt[posMem])
p->opt[posMem].posPrev = posMem - 1;
if (p->opt[cur].prev2)
{
p->opt[posMem - 1].prev1IsChar = False;
p->opt[posMem - 1].posPrev = p->opt[cur].posPrev2;
p->opt[posMem - 1].backPrev = p->opt[cur].backPrev2;
}
}
{
UInt32 posPrev = posMem;
UInt32 backCur = backMem;
backMem = p->opt[posPrev].backPrev;
posMem = p->opt[posPrev].posPrev;
p->opt[posPrev].backPrev = backCur;
p->opt[posPrev].posPrev = cur;
cur = posPrev;
}
}
while (cur != 0);
*backRes = p->opt[0].backPrev;
p->optimumCurrentIndex = p->opt[0].posPrev;
return p->optimumCurrentIndex;
}
#define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * 0x300)
static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
{
UInt32 numAvail, mainLen, numPairs, repMaxIndex, i, posState, lenEnd, len, cur;
UInt32 matchPrice, repMatchPrice, normalMatchPrice;
UInt32 reps[LZMA_NUM_REPS], repLens[LZMA_NUM_REPS];
UInt32 *matches;
const Byte *data;
Byte curByte, matchByte;
if (p->optimumEndIndex != p->optimumCurrentIndex)
{
const COptimal *opt = &p->opt[p->optimumCurrentIndex];
UInt32 lenRes = opt->posPrev - p->optimumCurrentIndex;
*backRes = opt->backPrev;
p->optimumCurrentIndex = opt->posPrev;
return lenRes;
}
p->optimumCurrentIndex = p->optimumEndIndex = 0;
if (p->additionalOffset == 0)
mainLen = ReadMatchDistances(p, &numPairs);
else
{
mainLen = p->longestMatchLength;
numPairs = p->numPairs;
}
numAvail = p->numAvail;
if (numAvail < 2)
{
*backRes = (UInt32)(-1);
return 1;
}
if (numAvail > LZMA_MATCH_LEN_MAX)
numAvail = LZMA_MATCH_LEN_MAX;
data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
repMaxIndex = 0;
for (i = 0; i < LZMA_NUM_REPS; i++)
{
UInt32 lenTest;
const Byte *data2;
reps[i] = p->reps[i];
data2 = data - (reps[i] + 1);
if (data[0] != data2[0] || data[1] != data2[1])
{
repLens[i] = 0;
continue;
}
for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++);
repLens[i] = lenTest;
if (lenTest > repLens[repMaxIndex])
repMaxIndex = i;
}
if (repLens[repMaxIndex] >= p->numFastBytes)
{
UInt32 lenRes;
*backRes = repMaxIndex;
lenRes = repLens[repMaxIndex];
MovePos(p, lenRes - 1);
return lenRes;
}
matches = p->matches;
if (mainLen >= p->numFastBytes)
{
*backRes = matches[numPairs - 1] + LZMA_NUM_REPS;
MovePos(p, mainLen - 1);
return mainLen;
}
curByte = *data;
matchByte = *(data - (reps[0] + 1));
if (mainLen < 2 && curByte != matchByte && repLens[repMaxIndex] < 2)
{
*backRes = (UInt32)-1;
return 1;
}
p->opt[0].state = (CState)p->state;
posState = (position & p->pbMask);
{
const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) +
(!IsCharState(p->state) ?
LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) :
LitEnc_GetPrice(probs, curByte, p->ProbPrices));
}
MakeAsChar(&p->opt[1]);
matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]);
repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]);
if (matchByte == curByte)
{
UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, p->state, posState);
if (shortRepPrice < p->opt[1].price)
{
p->opt[1].price = shortRepPrice;
MakeAsShortRep(&p->opt[1]);
}
}
lenEnd = ((mainLen >= repLens[repMaxIndex]) ? mainLen : repLens[repMaxIndex]);
if (lenEnd < 2)
{
*backRes = p->opt[1].backPrev;
return 1;
}
p->opt[1].posPrev = 0;
for (i = 0; i < LZMA_NUM_REPS; i++)
p->opt[0].backs[i] = reps[i];
len = lenEnd;
do
p->opt[len--].price = kInfinityPrice;
while (len >= 2);
for (i = 0; i < LZMA_NUM_REPS; i++)
{
UInt32 repLen = repLens[i];
UInt32 price;
if (repLen < 2)
continue;
price = repMatchPrice + GetPureRepPrice(p, i, p->state, posState);
do
{
UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][repLen - 2];
COptimal *opt = &p->opt[repLen];
if (curAndLenPrice < opt->price)
{
opt->price = curAndLenPrice;
opt->posPrev = 0;
opt->backPrev = i;
opt->prev1IsChar = False;
}
}
while (--repLen >= 2);
}
normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]);
len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2);
if (len <= mainLen)
{
UInt32 offs = 0;
while (len > matches[offs])
offs += 2;
for (; ; len++)
{
COptimal *opt;
UInt32 distance = matches[offs + 1];
UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN];
UInt32 lenToPosState = GetLenToPosState(len);
if (distance < kNumFullDistances)
curAndLenPrice += p->distancesPrices[lenToPosState][distance];
else
{
UInt32 slot;
GetPosSlot2(distance, slot);
curAndLenPrice += p->alignPrices[distance & kAlignMask] + p->posSlotPrices[lenToPosState][slot];
}
opt = &p->opt[len];
if (curAndLenPrice < opt->price)
{
opt->price = curAndLenPrice;
opt->posPrev = 0;
opt->backPrev = distance + LZMA_NUM_REPS;
opt->prev1IsChar = False;
}
if (len == matches[offs])
{
offs += 2;
if (offs == numPairs)
break;
}
}
}
cur = 0;
#ifdef SHOW_STAT2
if (position >= 0)
{
unsigned i;
printf("\n pos = %4X", position);
for (i = cur; i <= lenEnd; i++)
printf("\nprice[%4X] = %d", position - cur + i, p->opt[i].price);
}
#endif
for (;;)
{
UInt32 numAvailFull, newLen, numPairs, posPrev, state, posState, startLen;
UInt32 curPrice, curAnd1Price, matchPrice, repMatchPrice;
Bool nextIsChar;
Byte curByte, matchByte;
const Byte *data;
COptimal *curOpt;
COptimal *nextOpt;
cur++;
if (cur == lenEnd)
return Backward(p, backRes, cur);
newLen = ReadMatchDistances(p, &numPairs);
if (newLen >= p->numFastBytes)
{
p->numPairs = numPairs;
p->longestMatchLength = newLen;
return Backward(p, backRes, cur);
}
position++;
curOpt = &p->opt[cur];
posPrev = curOpt->posPrev;
if (curOpt->prev1IsChar)
{
posPrev--;
if (curOpt->prev2)
{
state = p->opt[curOpt->posPrev2].state;
if (curOpt->backPrev2 < LZMA_NUM_REPS)
state = kRepNextStates[state];
else
state = kMatchNextStates[state];
}
else
state = p->opt[posPrev].state;
state = kLiteralNextStates[state];
}
else
state = p->opt[posPrev].state;
if (posPrev == cur - 1)
{
if (IsShortRep(curOpt))
state = kShortRepNextStates[state];
else
state = kLiteralNextStates[state];
}
else
{
UInt32 pos;
const COptimal *prevOpt;
if (curOpt->prev1IsChar && curOpt->prev2)
{
posPrev = curOpt->posPrev2;
pos = curOpt->backPrev2;
state = kRepNextStates[state];
}
else
{
pos = curOpt->backPrev;
if (pos < LZMA_NUM_REPS)
state = kRepNextStates[state];
else
state = kMatchNextStates[state];
}
prevOpt = &p->opt[posPrev];
if (pos < LZMA_NUM_REPS)
{
UInt32 i;
reps[0] = prevOpt->backs[pos];
for (i = 1; i <= pos; i++)
reps[i] = prevOpt->backs[i - 1];
for (; i < LZMA_NUM_REPS; i++)
reps[i] = prevOpt->backs[i];
}
else
{
UInt32 i;
reps[0] = (pos - LZMA_NUM_REPS);
for (i = 1; i < LZMA_NUM_REPS; i++)
reps[i] = prevOpt->backs[i - 1];
}
}
curOpt->state = (CState)state;
curOpt->backs[0] = reps[0];
curOpt->backs[1] = reps[1];
curOpt->backs[2] = reps[2];
curOpt->backs[3] = reps[3];
curPrice = curOpt->price;
nextIsChar = False;
data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
curByte = *data;
matchByte = *(data - (reps[0] + 1));
posState = (position & p->pbMask);
curAnd1Price = curPrice + GET_PRICE_0(p->isMatch[state][posState]);
{
const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
curAnd1Price +=
(!IsCharState(state) ?
LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) :
LitEnc_GetPrice(probs, curByte, p->ProbPrices));
}
nextOpt = &p->opt[cur + 1];
if (curAnd1Price < nextOpt->price)
{
nextOpt->price = curAnd1Price;
nextOpt->posPrev = cur;
MakeAsChar(nextOpt);
nextIsChar = True;
}
matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]);
repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]);
if (matchByte == curByte && !(nextOpt->posPrev < cur && nextOpt->backPrev == 0))
{
UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, state, posState);
if (shortRepPrice <= nextOpt->price)
{
nextOpt->price = shortRepPrice;
nextOpt->posPrev = cur;
MakeAsShortRep(nextOpt);
nextIsChar = True;
}
}
numAvailFull = p->numAvail;
{
UInt32 temp = kNumOpts - 1 - cur;
if (temp < numAvailFull)
numAvailFull = temp;
}
if (numAvailFull < 2)
continue;
numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes);
if (!nextIsChar && matchByte != curByte) /* speed optimization */
{
/* try Literal + rep0 */
UInt32 temp;
UInt32 lenTest2;
const Byte *data2 = data - (reps[0] + 1);
UInt32 limit = p->numFastBytes + 1;
if (limit > numAvailFull)
limit = numAvailFull;
for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++);
lenTest2 = temp - 1;
if (lenTest2 >= 2)
{
UInt32 state2 = kLiteralNextStates[state];
UInt32 posStateNext = (position + 1) & p->pbMask;
UInt32 nextRepMatchPrice = curAnd1Price +
GET_PRICE_1(p->isMatch[state2][posStateNext]) +
GET_PRICE_1(p->isRep[state2]);
/* for (; lenTest2 >= 2; lenTest2--) */
{
UInt32 curAndLenPrice;
COptimal *opt;
UInt32 offset = cur + 1 + lenTest2;
while (lenEnd < offset)
p->opt[++lenEnd].price = kInfinityPrice;
curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
opt = &p->opt[offset];
if (curAndLenPrice < opt->price)
{
opt->price = curAndLenPrice;
opt->posPrev = cur + 1;
opt->backPrev = 0;
opt->prev1IsChar = True;
opt->prev2 = False;
}
}
}
}
startLen = 2; /* speed optimization */
{
UInt32 repIndex;
for (repIndex = 0; repIndex < LZMA_NUM_REPS; repIndex++)
{
UInt32 lenTest;
UInt32 lenTestTemp;
UInt32 price;
const Byte *data2 = data - (reps[repIndex] + 1);
if (data[0] != data2[0] || data[1] != data2[1])
continue;
for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++);
while (lenEnd < cur + lenTest)
p->opt[++lenEnd].price = kInfinityPrice;
lenTestTemp = lenTest;
price = repMatchPrice + GetPureRepPrice(p, repIndex, state, posState);
do
{
UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][lenTest - 2];
COptimal *opt = &p->opt[cur + lenTest];
if (curAndLenPrice < opt->price)
{
opt->price = curAndLenPrice;
opt->posPrev = cur;
opt->backPrev = repIndex;
opt->prev1IsChar = False;
}
}
while (--lenTest >= 2);
lenTest = lenTestTemp;
if (repIndex == 0)
startLen = lenTest + 1;
/* if (_maxMode) */
{
UInt32 lenTest2 = lenTest + 1;
UInt32 limit = lenTest2 + p->numFastBytes;
UInt32 nextRepMatchPrice;
if (limit > numAvailFull)
limit = numAvailFull;
for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);
lenTest2 -= lenTest + 1;
if (lenTest2 >= 2)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -