00001
00002
00003
00004
00005
00006
00007
00008 #include "pch.h"
00009 #include "zdeflate.h"
00010 #include <functional>
00011
00012 NAMESPACE_BEGIN(CryptoPP)
00013
00014 using namespace std;
00015
00016 LowFirstBitWriter::LowFirstBitWriter(BufferedTransformation *outQ)
00017 : Filter(outQ), m_counting(false), m_buffer(0), m_bitsBuffered(0)
00018 , m_bytesBuffered(0), m_outputBuffer(256)
00019 {
00020 }
00021
00022 void LowFirstBitWriter::StartCounting()
00023 {
00024 assert(!m_counting);
00025 m_counting = true;
00026 m_bitCount = 0;
00027 }
00028
00029 unsigned long LowFirstBitWriter::FinishCounting()
00030 {
00031 assert(m_counting);
00032 m_counting = false;
00033 return m_bitCount;
00034 }
00035
00036 void LowFirstBitWriter::PutBits(unsigned long value, unsigned int length)
00037 {
00038 if (m_counting)
00039 m_bitCount += length;
00040 else
00041 {
00042 m_buffer |= value << m_bitsBuffered;
00043 m_bitsBuffered += length;
00044 assert(m_bitsBuffered <= sizeof(unsigned long)*8);
00045 while (m_bitsBuffered >= 8)
00046 {
00047 m_outputBuffer[m_bytesBuffered++] = (byte)m_buffer;
00048 if (m_bytesBuffered == m_outputBuffer.size)
00049 {
00050 AttachedTransformation()->Put(m_outputBuffer, m_bytesBuffered);
00051 m_bytesBuffered = 0;
00052 }
00053 m_buffer >>= 8;
00054 m_bitsBuffered -= 8;
00055 }
00056 }
00057 }
00058
00059 void LowFirstBitWriter::FlushBitBuffer()
00060 {
00061 if (m_counting)
00062 m_bitCount += 8*(m_bitsBuffered > 0);
00063 else
00064 {
00065 if (m_bytesBuffered > 0)
00066 {
00067 AttachedTransformation()->Put(m_outputBuffer, m_bytesBuffered);
00068 m_bytesBuffered = 0;
00069 }
00070 if (m_bitsBuffered > 0)
00071 {
00072 AttachedTransformation()->Put((byte)m_buffer);
00073 m_buffer = 0;
00074 m_bitsBuffered = 0;
00075 }
00076 }
00077 }
00078
00079 HuffmanEncoder::HuffmanEncoder(const unsigned int *codeBits, unsigned int nCodes)
00080 {
00081 Initialize(codeBits, nCodes);
00082 }
00083
00084 struct HuffmanNode
00085 {
00086 inline bool operator<(const HuffmanNode &rhs) const {return freq < rhs.freq;}
00087 unsigned int symbol;
00088 union {unsigned int parent, depth, freq;};
00089 };
00090
00091 inline bool operator<(unsigned int i, const HuffmanNode &rhs) {return i < rhs.freq;}
00092
00093 void HuffmanEncoder::GenerateCodeLengths(unsigned int *codeBits, unsigned int maxCodeBits, const unsigned int *codeCounts, unsigned int nCodes)
00094 {
00095 assert(nCodes > 0);
00096 assert(nCodes <= (1 << maxCodeBits));
00097
00098 unsigned int i;
00099 SecBlock<HuffmanNode> tree(nCodes);
00100 for (i=0; i<nCodes; i++)
00101 {
00102 tree[i].symbol = i;
00103 tree[i].freq = codeCounts[i];
00104 }
00105 sort(tree.Begin(), tree.End());
00106 unsigned int treeBegin = upper_bound(tree.Begin(), tree.End(), 0) - tree.Begin();
00107 if (treeBegin == nCodes)
00108 {
00109 fill(codeBits, codeBits+nCodes, 0);
00110 return;
00111 }
00112 tree.Resize(nCodes + nCodes - treeBegin - 1);
00113
00114 unsigned int leastLeaf = treeBegin, leastInterior = nCodes;
00115 for (i=nCodes; i<tree.size; i++)
00116 {
00117 unsigned int least;
00118 least = (leastLeaf == nCodes || (leastInterior < i && tree[leastInterior].freq < tree[leastLeaf].freq)) ? leastInterior++ : leastLeaf++;
00119 tree[i].freq = tree[least].freq;
00120 tree[least].parent = i;
00121 least = (leastLeaf == nCodes || (leastInterior < i && tree[leastInterior].freq < tree[leastLeaf].freq)) ? leastInterior++ : leastLeaf++;
00122 tree[i].freq += tree[least].freq;
00123 tree[least].parent = i;
00124 }
00125
00126 tree[tree.size-1].depth = 0;
00127 if (tree.size >= 2)
00128 for (i=tree.size-2; i>=nCodes; i--)
00129 tree[i].depth = tree[tree[i].parent].depth + 1;
00130 unsigned int sum = 0;
00131 SecBlock<unsigned int> blCount(maxCodeBits+1);
00132 fill(blCount.Begin(), blCount.End(), 0);
00133 for (i=treeBegin; i<nCodes; i++)
00134 {
00135 unsigned int depth = STDMIN(maxCodeBits, tree[tree[i].parent].depth + 1);
00136 blCount[depth]++;
00137 sum += 1 << (maxCodeBits - depth);
00138 }
00139
00140 unsigned int overflow = sum > (1 << maxCodeBits) ? sum - (1 << maxCodeBits) : 0;
00141
00142 while (overflow--)
00143 {
00144 unsigned int bits = maxCodeBits-1;
00145 while (blCount[bits] == 0)
00146 bits--;
00147 blCount[bits]--;
00148 blCount[bits+1] += 2;
00149 assert(blCount[maxCodeBits] > 0);
00150 blCount[maxCodeBits]--;
00151 }
00152
00153 for (i=0; i<treeBegin; i++)
00154 codeBits[tree[i].symbol] = 0;
00155 unsigned int bits = maxCodeBits;
00156 for (i=treeBegin; i<nCodes; i++)
00157 {
00158 while (blCount[bits] == 0)
00159 bits--;
00160 codeBits[tree[i].symbol] = bits;
00161 blCount[bits]--;
00162 }
00163 assert(blCount[bits] == 0);
00164 }
00165
00166 void HuffmanEncoder::Initialize(const unsigned int *codeBits, unsigned int nCodes)
00167 {
00168 assert(nCodes > 0);
00169 unsigned int maxCodeBits = *max_element(codeBits, codeBits+nCodes);
00170 if (maxCodeBits == 0)
00171 return;
00172
00173 SecBlock<unsigned int> blCount(maxCodeBits+1);
00174 fill(blCount.Begin(), blCount.End(), 0);
00175 unsigned int i;
00176 for (i=0; i<nCodes; i++)
00177 blCount[codeBits[i]]++;
00178
00179 code_t code = 0;
00180 SecBlock<code_t> nextCode(maxCodeBits+1);
00181 nextCode[1] = 0;
00182 for (i=2; i<=maxCodeBits; i++)
00183 {
00184 code = (code + blCount[i-1]) << 1;
00185 nextCode[i] = code;
00186 }
00187 assert(maxCodeBits == 1 || code == (1 << maxCodeBits) - blCount[maxCodeBits]);
00188
00189 m_valueToCode.Resize(nCodes);
00190 for (i=0; i<nCodes; i++)
00191 {
00192 unsigned int len = m_valueToCode[i].len = codeBits[i];
00193 if (len != 0)
00194 m_valueToCode[i].code = bitReverse(nextCode[len]++) >> (8*sizeof(code_t)-len);
00195 }
00196 }
00197
00198 inline void HuffmanEncoder::Encode(LowFirstBitWriter &writer, value_t value) const
00199 {
00200 assert(m_valueToCode[value].len > 0);
00201 writer.PutBits(m_valueToCode[value].code, m_valueToCode[value].len);
00202 }
00203
00204 Deflator::Deflator(BufferedTransformation *outQ, unsigned int deflateLevel, unsigned int log2WindowSize)
00205 : LowFirstBitWriter(outQ)
00206 , m_log2WindowSize(log2WindowSize)
00207 , m_literalCounts(286), m_distanceCounts(30)
00208 , DSIZE(1<<log2WindowSize), DMASK(DSIZE-1), HSIZE(1<<log2WindowSize), HMASK(HSIZE-1)
00209 , m_head(HSIZE), m_prev(DSIZE)
00210 , m_byteBuffer(2*DSIZE), m_matchBuffer(DSIZE/2)
00211 {
00212 assert(0 <= deflateLevel && deflateLevel <= 9);
00213 assert(9 <= log2WindowSize && log2WindowSize <= 15);
00214
00215 unsigned int codeLengths[288];
00216 fill(codeLengths + 0, codeLengths + 144, 8);
00217 fill(codeLengths + 144, codeLengths + 256, 9);
00218 fill(codeLengths + 256, codeLengths + 280, 7);
00219 fill(codeLengths + 280, codeLengths + 288, 8);
00220 m_staticLiteralEncoder.Initialize(codeLengths, 288);
00221 fill(codeLengths + 0, codeLengths + 32, 5);
00222 m_staticDistanceEncoder.Initialize(codeLengths, 32);
00223
00224 SetDeflateLevel(deflateLevel);
00225 Reset();
00226 }
00227
00228 void Deflator::Reset()
00229 {
00230 assert(m_bitsBuffered == 0);
00231
00232 m_headerWritten = false;
00233 m_matchAvailable = false;
00234 m_dictionaryEnd = 0;
00235 m_stringStart = 0;
00236 m_lookahead = 0;
00237 m_minLookahead = MAX_MATCH;
00238 m_previousMatch = 0;
00239 m_previousLength = 0;
00240 m_matchBufferEnd = 0;
00241 m_blockStart = 0;
00242 m_blockLength = 0;
00243
00244
00245 fill(m_head.Begin(), m_head.End(), 0);
00246
00247 fill(m_literalCounts.Begin(), m_literalCounts.End(), 0);
00248 fill(m_distanceCounts.Begin(), m_distanceCounts.End(), 0);
00249 }
00250
00251 void Deflator::SetDeflateLevel(unsigned int deflateLevel)
00252 {
00253 unsigned int configurationTable[10][4] = {
00254
00255 {0, 0, 0, 0},
00256 {4, 3, 8, 4},
00257 {4, 3, 16, 8},
00258 {4, 3, 32, 32},
00259 {4, 4, 16, 16},
00260 {8, 16, 32, 32},
00261 {8, 16, 128, 128},
00262 {8, 32, 128, 256},
00263 {32, 128, 258, 1024},
00264 {32, 258, 258, 4096}};
00265
00266 GOOD_MATCH = configurationTable[deflateLevel][0];
00267 MAX_LAZYLENGTH = configurationTable[deflateLevel][1];
00268 MAX_CHAIN_LENGTH = configurationTable[deflateLevel][3];
00269
00270 m_deflateLevel = deflateLevel;
00271 }
00272
00273 unsigned int Deflator::FillWindow(const byte *str, unsigned int length)
00274 {
00275 unsigned int accepted = STDMIN(length, 2*DSIZE-(m_stringStart+m_lookahead));
00276
00277 if (m_stringStart >= 2*DSIZE - MAX_MATCH)
00278 {
00279 if (m_blockStart < DSIZE)
00280 EndBlock(false);
00281
00282 memcpy(m_byteBuffer, m_byteBuffer + DSIZE, DSIZE);
00283
00284 m_dictionaryEnd = m_dictionaryEnd < DSIZE ? 0 : m_dictionaryEnd-DSIZE;
00285 assert(m_stringStart >= DSIZE);
00286 m_stringStart -= DSIZE;
00287 assert(m_previousMatch >= DSIZE || m_previousLength < MIN_MATCH);
00288 m_previousMatch -= DSIZE;
00289 assert(m_blockStart >= DSIZE);
00290 m_blockStart -= DSIZE;
00291
00292 unsigned int i, j;
00293
00294 for (i=0; i<HSIZE; i++)
00295 m_head[i] = (j=m_head[i]) < DSIZE ? 0 : j-DSIZE;
00296
00297 for (i=0; i<DSIZE; i++)
00298 m_prev[i] = (j=m_prev[i]) < DSIZE ? 0 : j-DSIZE;
00299
00300 accepted = STDMIN(accepted + DSIZE, length);
00301 }
00302 assert(accepted > 0);
00303
00304 memcpy(m_byteBuffer + m_stringStart + m_lookahead, str, accepted);
00305 m_lookahead += accepted;
00306 return accepted;
00307 }
00308
00309 inline unsigned int Deflator::ComputeHash(const byte *str) const
00310 {
00311 assert(str+3 <= m_byteBuffer + m_stringStart + m_lookahead);
00312 return ((str[0] << 10) ^ (str[1] << 5) ^ str[2]) & HMASK;
00313 }
00314
00315 unsigned int Deflator::LongestMatch(unsigned int &bestMatch) const
00316 {
00317 assert(m_previousLength < MAX_MATCH);
00318
00319 bestMatch = 0;
00320 unsigned int bestLength = STDMAX(m_previousLength, (unsigned int)MIN_MATCH-1);
00321 if (m_lookahead <= bestLength)
00322 return 0;
00323
00324 const byte *scan = m_byteBuffer + m_stringStart, *scanEnd = scan + STDMIN((unsigned int)MAX_MATCH, m_lookahead);
00325 unsigned int limit = m_stringStart > (DSIZE-MAX_MATCH) ? m_stringStart - (DSIZE-MAX_MATCH) : 0;
00326 unsigned int current = m_head[ComputeHash(scan)];
00327
00328 unsigned int chainLength = MAX_CHAIN_LENGTH;
00329 if (m_previousLength >= GOOD_MATCH)
00330 chainLength >>= 2;
00331
00332 while (current > limit && --chainLength > 0)
00333 {
00334 const byte *match = m_byteBuffer + current;
00335 assert(scan + bestLength < m_byteBuffer + m_stringStart + m_lookahead);
00336 if (scan[bestLength-1] == match[bestLength-1] && scan[bestLength] == match[bestLength] && scan[0] == match[0] && scan[1] == match[1])
00337 {
00338 assert(scan[2] == match[2]);
00339 unsigned int len = std::mismatch(scan+3, scanEnd, match+3).first - scan;
00340 assert(len != bestLength);
00341 if (len > bestLength)
00342 {
00343 bestLength = len;
00344 bestMatch = current;
00345 if (len == (scanEnd - scan))
00346 break;
00347 }
00348 }
00349 current = m_prev[current & DMASK];
00350 }
00351 return (bestMatch > 0) ? bestLength : 0;
00352 }
00353
00354 inline void Deflator::InsertString(unsigned int start)
00355 {
00356 unsigned int hash = ComputeHash(m_byteBuffer + start);
00357 m_prev[start & DMASK] = m_head[hash];
00358 m_head[hash] = start;
00359 }
00360
00361 void Deflator::ProcessBuffer()
00362 {
00363 if (!m_headerWritten)
00364 {
00365 WritePrestreamHeader();
00366 m_headerWritten = true;
00367 }
00368
00369 if (m_deflateLevel == 0)
00370 {
00371 while (m_lookahead > 0)
00372 {
00373 LiteralByte(m_byteBuffer[m_stringStart++]);
00374 m_lookahead--;
00375 }
00376 return;
00377 }
00378
00379 while (m_lookahead > m_minLookahead)
00380 {
00381 while (m_dictionaryEnd < m_stringStart && m_dictionaryEnd+3 <= m_stringStart+m_lookahead)
00382 InsertString(m_dictionaryEnd++);
00383
00384 if (m_matchAvailable)
00385 {
00386 unsigned int matchPosition, matchLength;
00387 bool usePreviousMatch;
00388 if (m_previousLength >= MAX_LAZYLENGTH)
00389 usePreviousMatch = true;
00390 else
00391 {
00392 matchLength = LongestMatch(matchPosition);
00393 usePreviousMatch = (m_previousLength > 0 && matchLength == 0);
00394 }
00395 if (usePreviousMatch)
00396 {
00397 MatchFound(m_stringStart-1-m_previousMatch, m_previousLength);
00398 m_stringStart += m_previousLength-1;
00399 m_lookahead -= m_previousLength-1;
00400 m_matchAvailable = false;
00401 m_previousLength = 0;
00402 }
00403 else
00404 {
00405 m_previousLength = matchLength;
00406 m_previousMatch = matchPosition;
00407 LiteralByte(m_byteBuffer[m_stringStart-1]);
00408 m_stringStart++;
00409 m_lookahead--;
00410 }
00411 }
00412 else
00413 {
00414 m_previousLength = LongestMatch(m_previousMatch);
00415 m_matchAvailable = true;
00416 m_stringStart++;
00417 m_lookahead--;
00418 }
00419 }
00420 assert(m_stringStart - (m_blockStart+m_blockLength) <= 1);
00421 if (m_minLookahead == 0 && m_matchAvailable)
00422 {
00423 LiteralByte(m_byteBuffer[m_stringStart-1]);
00424 m_matchAvailable = false;
00425 }
00426 }
00427
00428 void Deflator::Put(const byte *str, unsigned int length)
00429 {
00430 ProcessUncompressedData(str, length);
00431
00432 unsigned int accepted = 0;
00433 while (accepted < length)
00434 {
00435 accepted += FillWindow(str+accepted, length-accepted);
00436 ProcessBuffer();
00437 }
00438 }
00439
00440 void Deflator::Flush(bool completeFlush, int propagation)
00441 {
00442 m_minLookahead = 0;
00443 ProcessBuffer();
00444 m_minLookahead = MAX_MATCH;
00445 EndBlock(false);
00446 EncodeBlock(false, STORED);
00447 Filter::Flush(completeFlush, propagation);
00448 }
00449
00450 void Deflator::MessageEnd(int propagation)
00451 {
00452 m_minLookahead = 0;
00453 ProcessBuffer();
00454 EndBlock(true);
00455 FlushBitBuffer();
00456 WritePoststreamTail();
00457 Filter::MessageEnd(propagation);
00458 Reset();
00459 }
00460
00461 void Deflator::LiteralByte(byte b)
00462 {
00463 m_matchBuffer[m_matchBufferEnd++].literalCode = b;
00464 m_literalCounts[b]++;
00465
00466 if (m_blockStart+(++m_blockLength) == m_byteBuffer.size || m_matchBufferEnd == m_matchBuffer.size)
00467 EndBlock(false);
00468 }
00469
00470 void Deflator::MatchFound(unsigned int distance, unsigned int length)
00471 {
00472 static const unsigned int lengthCodes[] = {
00473 257, 258, 259, 260, 261, 262, 263, 264, 265, 265, 266, 266, 267, 267, 268, 268,
00474 269, 269, 269, 269, 270, 270, 270, 270, 271, 271, 271, 271, 272, 272, 272, 272,
00475 273, 273, 273, 273, 273, 273, 273, 273, 274, 274, 274, 274, 274, 274, 274, 274,
00476 275, 275, 275, 275, 275, 275, 275, 275, 276, 276, 276, 276, 276, 276, 276, 276,
00477 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
00478 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278,
00479 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279,
00480 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280,
00481 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
00482 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
00483 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282,
00484 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282,
00485 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283,
00486 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283,
00487 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
00488 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 285};
00489 static const unsigned int lengthBases[] = {3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258};
00490 static const unsigned int distanceBases[30] =
00491 {1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577};
00492
00493 EncodedMatch &m = m_matchBuffer[m_matchBufferEnd++];
00494 unsigned int lengthCode = lengthCodes[length-3];
00495 m.literalCode = lengthCode;
00496 m.literalExtra = length - lengthBases[lengthCode-257];
00497 unsigned int distanceCode = upper_bound(distanceBases, distanceBases+30, distance) - distanceBases - 1;
00498 m.distanceCode = distanceCode;
00499 m.distanceExtra = distance - distanceBases[distanceCode];
00500
00501 m_literalCounts[lengthCode]++;
00502 m_distanceCounts[distanceCode]++;
00503
00504 if (m_blockStart+(m_blockLength+=length) == m_byteBuffer.size || m_matchBufferEnd == m_matchBuffer.size)
00505 EndBlock(false);
00506 }
00507
00508 inline unsigned int CodeLengthEncode(const unsigned int *begin,
00509 const unsigned int *end,
00510 const unsigned int *& p,
00511 unsigned int &extraBits,
00512 unsigned int &extraBitsLength)
00513 {
00514 unsigned int v = *p;
00515 if ((end-p) >= 3)
00516 {
00517 const unsigned int *oldp = p;
00518 if (v==0 && p[1]==0 && p[2]==0)
00519 {
00520 for (p=p+3; *p==0 && p!=end && p!=oldp+138; p++) {}
00521 unsigned int repeat = p - oldp;
00522 if (repeat <= 10)
00523 {
00524 extraBits = repeat-3;
00525 extraBitsLength = 3;
00526 return 17;
00527 }
00528 else
00529 {
00530 extraBits = repeat-11;
00531 extraBitsLength = 7;
00532 return 18;
00533 }
00534 }
00535 else if (p!=begin && v==p[-1] && v==p[1] && v==p[2])
00536 {
00537 for (p=p+3; *p==v && p!=end && p!=oldp+6; p++) {}
00538 unsigned int repeat = p - oldp;
00539 extraBits = repeat-3;
00540 extraBitsLength = 2;
00541 return 16;
00542 }
00543 }
00544 p++;
00545 extraBits = 0;
00546 extraBitsLength = 0;
00547 return v;
00548 }
00549
00550 void Deflator::EncodeBlock(bool eof, unsigned int blockType)
00551 {
00552 PutBits(eof, 1);
00553 PutBits(blockType, 2);
00554
00555 if (blockType == STORED)
00556 {
00557 assert(m_blockStart + m_blockLength <= m_byteBuffer.size);
00558 FlushBitBuffer();
00559 AttachedTransformation()->PutWord16(m_blockLength, false);
00560 AttachedTransformation()->PutWord16(~m_blockLength, false);
00561 AttachedTransformation()->Put(m_byteBuffer + m_blockStart, m_blockLength);
00562 }
00563 else
00564 {
00565 if (blockType == DYNAMIC)
00566 {
00567 SecBlock<unsigned int> literalCodeLengths(286), distanceCodeLengths(30);
00568 #if defined(_MSC_VER) && !defined(__MWERKS__) // VC60 workaround
00569 typedef reverse_iterator<unsigned int *, unsigned int> RevIt;
00570 #else
00571 typedef reverse_iterator<unsigned int *> RevIt;
00572 #endif
00573
00574 m_literalCounts[256] = 1;
00575 HuffmanEncoder::GenerateCodeLengths(literalCodeLengths, 15, m_literalCounts, 286);
00576 m_dynamicLiteralEncoder.Initialize(literalCodeLengths, 286);
00577 unsigned int hlit = find_if(RevIt(literalCodeLengths.End()), RevIt(literalCodeLengths.Begin()+257), bind2nd(not_equal_to<unsigned int>(), 0)).base() - (literalCodeLengths.Begin()+257);
00578
00579 HuffmanEncoder::GenerateCodeLengths(distanceCodeLengths, 15, m_distanceCounts, 30);
00580 m_dynamicDistanceEncoder.Initialize(distanceCodeLengths, 30);
00581 unsigned int hdist = find_if(RevIt(distanceCodeLengths.End()), RevIt(distanceCodeLengths.Begin()+1), bind2nd(not_equal_to<unsigned int>(), 0)).base() - (distanceCodeLengths.Begin()+1);
00582
00583 SecBlock<unsigned int> combinedLengths(hlit+257+hdist+1);
00584 memcpy(combinedLengths, literalCodeLengths, (hlit+257)*sizeof(unsigned int));
00585 memcpy(combinedLengths+hlit+257, distanceCodeLengths, (hdist+1)*sizeof(unsigned int));
00586
00587 SecBlock<unsigned int> codeLengthCodeCounts(19), codeLengthCodeLengths(19);
00588 fill(codeLengthCodeCounts.Begin(), codeLengthCodeCounts.End(), 0);
00589 const unsigned int *p = combinedLengths.Begin(), *begin = combinedLengths.Begin(), *end = combinedLengths.End();
00590 while (p != end)
00591 {
00592 unsigned int code, extraBits, extraBitsLength;
00593 code = CodeLengthEncode(begin, end, p, extraBits, extraBitsLength);
00594 codeLengthCodeCounts[code]++;
00595 }
00596 HuffmanEncoder::GenerateCodeLengths(codeLengthCodeLengths, 7, codeLengthCodeCounts, 19);
00597 HuffmanEncoder codeLengthEncoder(codeLengthCodeLengths, 19);
00598 static const unsigned int border[] = {
00599 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
00600 unsigned int hclen = 19;
00601 while (hclen > 4 && codeLengthCodeLengths[border[hclen-1]] == 0)
00602 hclen--;
00603 hclen -= 4;
00604
00605 PutBits(hlit, 5);
00606 PutBits(hdist, 5);
00607 PutBits(hclen, 4);
00608
00609 for (unsigned int i=0; i<hclen+4; i++)
00610 PutBits(codeLengthCodeLengths[border[i]], 3);
00611
00612 p = combinedLengths.Begin();
00613 while (p != end)
00614 {
00615 unsigned int code, extraBits, extraBitsLength;
00616 code = CodeLengthEncode(begin, end, p, extraBits, extraBitsLength);
00617 codeLengthEncoder.Encode(*this, code);
00618 PutBits(extraBits, extraBitsLength);
00619 }
00620 }
00621
00622 static const unsigned int lengthExtraBits[] = {
00623 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
00624 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0};
00625 static const unsigned int distanceExtraBits[] = {
00626 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
00627 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
00628 12, 12, 13, 13};
00629
00630 const HuffmanEncoder &literalEncoder = (blockType == STATIC) ? m_staticLiteralEncoder : m_dynamicLiteralEncoder;
00631 const HuffmanEncoder &distanceEncoder = (blockType == STATIC) ? m_staticDistanceEncoder : m_dynamicDistanceEncoder;
00632
00633 for (unsigned int i=0; i<m_matchBufferEnd; i++)
00634 {
00635 unsigned int literalCode = m_matchBuffer[i].literalCode;
00636 literalEncoder.Encode(*this, literalCode);
00637 if (literalCode >= 257)
00638 {
00639 assert(literalCode <= 285);
00640 PutBits(m_matchBuffer[i].literalExtra, lengthExtraBits[literalCode-257]);
00641 unsigned int distanceCode = m_matchBuffer[i].distanceCode;
00642 distanceEncoder.Encode(*this, distanceCode);
00643 PutBits(m_matchBuffer[i].distanceExtra, distanceExtraBits[distanceCode]);
00644 }
00645 }
00646 literalEncoder.Encode(*this, 256);
00647 }
00648 }
00649
00650 void Deflator::EndBlock(bool eof)
00651 {
00652 if (m_matchBufferEnd == 0 && !eof)
00653 return;
00654
00655 if (m_deflateLevel == 0)
00656 EncodeBlock(eof, STORED);
00657 else if (m_blockLength < 128)
00658 EncodeBlock(eof, STATIC);
00659 else
00660 {
00661 unsigned int storedLen = 8*(m_blockLength+4) + RoundUpToMultipleOf(m_bitsBuffered+3, 8)-m_bitsBuffered;
00662 StartCounting();
00663 EncodeBlock(eof, STATIC);
00664 unsigned int staticLen = FinishCounting();
00665 StartCounting();
00666 EncodeBlock(eof, DYNAMIC);
00667 unsigned int dynamicLen = FinishCounting();
00668
00669 if (storedLen <= staticLen && storedLen <= dynamicLen)
00670 EncodeBlock(eof, STORED);
00671 else if (staticLen <= dynamicLen)
00672 EncodeBlock(eof, STATIC);
00673 else
00674 EncodeBlock(eof, DYNAMIC);
00675 }
00676
00677 m_matchBufferEnd = 0;
00678 m_blockStart += m_blockLength;
00679 m_blockLength = 0;
00680 fill(m_literalCounts.Begin(), m_literalCounts.End(), 0);
00681 fill(m_distanceCounts.Begin(), m_distanceCounts.End(), 0);
00682 }
00683
00684 NAMESPACE_END