Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

zdeflate.cpp

00001 // zdeflate.cpp - written and placed in the public domain by Wei Dai
00002 
00003 // Many of the algorithms and tables used here came from the deflate implementation
00004 // by Jean-loup Gailly, which was included in Crypto++ 4.0 and earlier. I completely
00005 // rewrote it in order to fix a bug that I could not figure out. This code
00006 // is less clever, but hopefully more understandable and maintainable.
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         {       // special case for no codes
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;         // assume this object won't be used
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         // m_prev will be initialized automaticly in InsertString
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                 /*      good lazy nice chain */
00255                 /* 0 */ {0,    0,  0,    0},  /* store only */
00256                 /* 1 */ {4,    3,  8,    4},  /* maximum speed, no lazy matches */
00257                 /* 2 */ {4,    3, 16,    8},
00258                 /* 3 */ {4,    3, 32,   32},
00259                 /* 4 */ {4,    4, 16,   16},  /* lazy matches */
00260                 /* 5 */ {8,   16, 32,   32},
00261                 /* 6 */ {8,   16, 128, 128},
00262                 /* 7 */ {8,   32, 128, 256},
00263                 /* 8 */ {32, 128, 258, 1024},
00264                 /* 9 */ {32, 258, 258, 4096}}; /* maximum compression */
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[] = {    // Order of the bit length code lengths
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);      // end of block
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

Generated at Mon Jan 15 01:16:38 2001 for Crypto++ by doxygen1.2.4 written by Dimitri van Heesch, © 1997-2000