17 NAMESPACE_BEGIN(CryptoPP)
22 :
Filter(attachment), m_counting(false), m_buffer(0), m_bitsBuffered(0), m_bytesBuffered(0)
26 void LowFirstBitWriter::StartCounting()
33 unsigned long LowFirstBitWriter::FinishCounting()
40 void LowFirstBitWriter::PutBits(
unsigned long value,
unsigned int length)
46 m_buffer |= value << m_bitsBuffered;
47 m_bitsBuffered += length;
48 assert(m_bitsBuffered <=
sizeof(
unsigned long)*8);
49 while (m_bitsBuffered >= 8)
51 m_outputBuffer[m_bytesBuffered++] = (byte)m_buffer;
52 if (m_bytesBuffered == m_outputBuffer.size())
63 void LowFirstBitWriter::FlushBitBuffer()
66 m_bitCount += 8*(m_bitsBuffered > 0);
69 if (m_bytesBuffered > 0)
74 if (m_bitsBuffered > 0)
83 void LowFirstBitWriter::ClearBitBuffer()
90 HuffmanEncoder::HuffmanEncoder(
const unsigned int *codeBits,
unsigned int nCodes)
92 Initialize(codeBits, nCodes);
98 union {
size_t parent;
unsigned depth, freq;};
103 inline bool operator()(
unsigned int lhs,
const HuffmanNode &rhs) {
return lhs < rhs.freq;}
104 inline bool operator()(
const HuffmanNode &lhs,
const HuffmanNode &rhs)
const {
return lhs.freq < rhs.freq;}
106 inline bool operator()(
const HuffmanNode &lhs,
unsigned int rhs) {
return lhs.freq < rhs;}
109 void HuffmanEncoder::GenerateCodeLengths(
unsigned int *codeBits,
unsigned int maxCodeBits,
const unsigned int *codeCounts,
size_t nCodes)
112 assert(nCodes <= ((
size_t)1 << maxCodeBits));
116 for (i=0; i<nCodes; i++)
119 tree[i].freq = codeCounts[i];
122 size_t treeBegin = upper_bound(tree.begin(), tree.end(), 0,
FreqLessThan()) - tree.begin();
123 if (treeBegin == nCodes)
125 fill(codeBits, codeBits+nCodes, 0);
128 tree.resize(nCodes + nCodes - treeBegin - 1);
130 size_t leastLeaf = treeBegin, leastInterior = nCodes;
131 for (i=nCodes; i<tree.size(); i++)
134 least = (leastLeaf == nCodes || (leastInterior < i && tree[leastInterior].freq < tree[leastLeaf].freq)) ? leastInterior++ : leastLeaf++;
135 tree[i].freq = tree[least].freq;
136 tree[least].parent = i;
137 least = (leastLeaf == nCodes || (leastInterior < i && tree[leastInterior].freq < tree[leastLeaf].freq)) ? leastInterior++ : leastLeaf++;
138 tree[i].freq += tree[least].freq;
139 tree[least].parent = i;
142 tree[tree.size()-1].depth = 0;
143 if (tree.size() >= 2)
144 for (i=tree.size()-2; i>=nCodes; i--)
145 tree[i].depth = tree[tree[i].parent].depth + 1;
146 unsigned int sum = 0;
148 fill(blCount.begin(), blCount.end(), 0);
149 for (i=treeBegin; i<nCodes; i++)
151 size_t depth = STDMIN(maxCodeBits, tree[tree[i].parent].depth + 1);
153 sum += 1 << (maxCodeBits - depth);
156 unsigned int overflow = sum > (
unsigned int)(1 << maxCodeBits) ? sum - (1 << maxCodeBits) : 0;
160 unsigned int bits = maxCodeBits-1;
161 while (blCount[bits] == 0)
164 blCount[bits+1] += 2;
165 assert(blCount[maxCodeBits] > 0);
166 blCount[maxCodeBits]--;
169 for (i=0; i<treeBegin; i++)
170 codeBits[tree[i].symbol] = 0;
171 unsigned int bits = maxCodeBits;
172 for (i=treeBegin; i<nCodes; i++)
174 while (blCount[bits] == 0)
176 codeBits[tree[i].symbol] = bits;
179 assert(blCount[bits] == 0);
182 void HuffmanEncoder::Initialize(
const unsigned int *codeBits,
unsigned int nCodes)
185 unsigned int maxCodeBits = *max_element(codeBits, codeBits+nCodes);
186 if (maxCodeBits == 0)
190 fill(blCount.begin(), blCount.end(), 0);
192 for (i=0; i<nCodes; i++)
193 blCount[codeBits[i]]++;
198 for (i=2; i<=maxCodeBits; i++)
200 code = (code + blCount[i-1]) << 1;
203 assert(maxCodeBits == 1 || code == (1 << maxCodeBits) - blCount[maxCodeBits]);
205 m_valueToCode.resize(nCodes);
206 for (i=0; i<nCodes; i++)
208 unsigned int len = m_valueToCode[i].len = codeBits[i];
210 m_valueToCode[i].code = BitReverse(nextCode[len]++) >> (8*
sizeof(code_t)-len);
214 inline void HuffmanEncoder::Encode(
LowFirstBitWriter &writer, value_t value)
const
216 assert(m_valueToCode[value].len > 0);
217 writer.PutBits(m_valueToCode[value].code, m_valueToCode[value].len);
224 InitializeStaticEncoders();
225 IsolatedInitialize(MakeParameters(
"DeflateLevel", deflateLevel)(
"Log2WindowSize", log2WindowSize)(
"DetectUncompressible", detectUncompressible));
232 InitializeStaticEncoders();
233 IsolatedInitialize(parameters);
236 void Deflator::InitializeStaticEncoders()
238 unsigned int codeLengths[288];
239 fill(codeLengths + 0, codeLengths + 144, 8);
240 fill(codeLengths + 144, codeLengths + 256, 9);
241 fill(codeLengths + 256, codeLengths + 280, 7);
242 fill(codeLengths + 280, codeLengths + 288, 8);
243 m_staticLiteralEncoder.Initialize(codeLengths, 288);
244 fill(codeLengths + 0, codeLengths + 32, 5);
245 m_staticDistanceEncoder.Initialize(codeLengths, 32);
248 void Deflator::IsolatedInitialize(
const NameValuePairs ¶meters)
251 if (!(MIN_LOG2_WINDOW_SIZE <= log2WindowSize && log2WindowSize <= MAX_LOG2_WINDOW_SIZE))
252 throw InvalidArgument(
"Deflator: " + IntToString(log2WindowSize) +
" is an invalid window size");
254 m_log2WindowSize = log2WindowSize;
255 DSIZE = 1 << m_log2WindowSize;
257 HSIZE = 1 << m_log2WindowSize;
259 m_byteBuffer.
New(2*DSIZE);
262 m_matchBuffer.New(DSIZE/2);
267 m_compressibleDeflateLevel = detectUncompressible ? m_deflateLevel : 0;
270 void Deflator::Reset(
bool forceReset)
275 assert(m_bitsBuffered == 0);
277 m_headerWritten =
false;
278 m_matchAvailable =
false;
282 m_minLookahead = MAX_MATCH;
283 m_matchBufferEnd = 0;
291 fill(m_head.begin(), m_head.end(), 0);
293 fill(m_literalCounts.begin(), m_literalCounts.end(), 0);
294 fill(m_distanceCounts.begin(), m_distanceCounts.end(), 0);
299 if (!(MIN_DEFLATE_LEVEL <= deflateLevel && deflateLevel <= MAX_DEFLATE_LEVEL))
300 throw InvalidArgument(
"Deflator: " + IntToString(deflateLevel) +
" is an invalid deflate level");
302 if (deflateLevel == m_deflateLevel)
307 static const unsigned int configurationTable[10][4] = {
317 {32, 128, 258, 1024},
318 {32, 258, 258, 4096}};
320 GOOD_MATCH = configurationTable[deflateLevel][0];
321 MAX_LAZYLENGTH = configurationTable[deflateLevel][1];
322 MAX_CHAIN_LENGTH = configurationTable[deflateLevel][3];
324 m_deflateLevel = deflateLevel;
327 unsigned int Deflator::FillWindow(
const byte *str,
size_t length)
329 unsigned int maxBlockSize = (
unsigned int)STDMIN(2UL*DSIZE, 0xffffUL);
331 if (m_stringStart >= maxBlockSize - MAX_MATCH)
333 if (m_blockStart < DSIZE)
336 memcpy(m_byteBuffer, m_byteBuffer + DSIZE, DSIZE);
338 m_dictionaryEnd = m_dictionaryEnd < DSIZE ? 0 : m_dictionaryEnd-DSIZE;
339 assert(m_stringStart >= DSIZE);
340 m_stringStart -= DSIZE;
341 assert(!m_matchAvailable || m_previousMatch >= DSIZE);
342 m_previousMatch -= DSIZE;
343 assert(m_blockStart >= DSIZE);
344 m_blockStart -= DSIZE;
348 for (i=0; i<HSIZE; i++)
349 m_head[i] = SaturatingSubtract(m_head[i], DSIZE);
351 for (i=0; i<DSIZE; i++)
352 m_prev[i] = SaturatingSubtract(m_prev[i], DSIZE);
355 assert(maxBlockSize > m_stringStart+m_lookahead);
356 unsigned int accepted = UnsignedMin(maxBlockSize-(m_stringStart+m_lookahead), length);
357 assert(accepted > 0);
358 memcpy(m_byteBuffer + m_stringStart + m_lookahead, str, accepted);
359 m_lookahead += accepted;
363 inline unsigned int Deflator::ComputeHash(
const byte *str)
const
365 assert(str+3 <= m_byteBuffer + m_stringStart + m_lookahead);
366 return ((str[0] << 10) ^ (str[1] << 5) ^ str[2]) & HMASK;
369 unsigned int Deflator::LongestMatch(
unsigned int &bestMatch)
const
371 assert(m_previousLength < MAX_MATCH);
374 unsigned int bestLength = STDMAX(m_previousLength, (
unsigned int)MIN_MATCH-1);
375 if (m_lookahead <= bestLength)
378 const byte *scan = m_byteBuffer + m_stringStart, *scanEnd = scan + STDMIN((
unsigned int)MAX_MATCH, m_lookahead);
379 unsigned int limit = m_stringStart > (DSIZE-MAX_MATCH) ? m_stringStart - (DSIZE-MAX_MATCH) : 0;
380 unsigned int current = m_head[ComputeHash(scan)];
382 unsigned int chainLength = MAX_CHAIN_LENGTH;
383 if (m_previousLength >= GOOD_MATCH)
386 while (current > limit && --chainLength > 0)
388 const byte *match = m_byteBuffer + current;
389 assert(scan + bestLength < m_byteBuffer + m_stringStart + m_lookahead);
390 if (scan[bestLength-1] == match[bestLength-1] && scan[bestLength] == match[bestLength] && scan[0] == match[0] && scan[1] == match[1])
392 assert(scan[2] == match[2]);
393 unsigned int len = (
unsigned int)(
394 #
if defined(_STDEXT_BEGIN) && !(defined(_MSC_VER) && (_MSC_VER < 1400 || _MSC_VER >= 1600)) && !defined(_STLPORT_VERSION)
395 stdext::unchecked_mismatch
400 (stdext::make_unchecked_array_iterator(scan)+3, stdext::make_unchecked_array_iterator(scanEnd), stdext::make_unchecked_array_iterator(match)+3).first - stdext::make_unchecked_array_iterator(scan));
402 (scan+3, scanEnd, match+3).first - scan);
404 assert(len != bestLength);
405 if (len > bestLength)
409 if (len == (scanEnd - scan))
413 current = m_prev[current & DMASK];
415 return (bestMatch > 0) ? bestLength : 0;
418 inline void Deflator::InsertString(
unsigned int start)
420 unsigned int hash = ComputeHash(m_byteBuffer + start);
421 m_prev[start & DMASK] = m_head[hash];
422 m_head[hash] = start;
425 void Deflator::ProcessBuffer()
427 if (!m_headerWritten)
429 WritePrestreamHeader();
430 m_headerWritten =
true;
433 if (m_deflateLevel == 0)
435 m_stringStart += m_lookahead;
437 m_blockLength = m_stringStart - m_blockStart;
438 m_matchAvailable =
false;
442 while (m_lookahead > m_minLookahead)
444 while (m_dictionaryEnd < m_stringStart && m_dictionaryEnd+3 <= m_stringStart+m_lookahead)
445 InsertString(m_dictionaryEnd++);
447 if (m_matchAvailable)
449 unsigned int matchPosition, matchLength;
450 bool usePreviousMatch;
451 if (m_previousLength >= MAX_LAZYLENGTH)
452 usePreviousMatch =
true;
455 matchLength = LongestMatch(matchPosition);
456 usePreviousMatch = (matchLength == 0);
458 if (usePreviousMatch)
460 MatchFound(m_stringStart-1-m_previousMatch, m_previousLength);
461 m_stringStart += m_previousLength-1;
462 m_lookahead -= m_previousLength-1;
463 m_matchAvailable =
false;
467 m_previousLength = matchLength;
468 m_previousMatch = matchPosition;
469 LiteralByte(m_byteBuffer[m_stringStart-1]);
476 m_previousLength = 0;
477 m_previousLength = LongestMatch(m_previousMatch);
478 if (m_previousLength)
479 m_matchAvailable =
true;
481 LiteralByte(m_byteBuffer[m_stringStart]);
486 assert(m_stringStart - (m_blockStart+m_blockLength) == (
unsigned int)m_matchAvailable);
489 if (m_minLookahead == 0 && m_matchAvailable)
491 LiteralByte(m_byteBuffer[m_stringStart-1]);
492 m_matchAvailable =
false;
496 size_t Deflator::Put2(
const byte *str,
size_t length,
int messageEnd,
bool blocking)
502 while (accepted < length)
504 unsigned int newAccepted = FillWindow(str+accepted, length-accepted);
507 ProcessUncompressedData(str+accepted, newAccepted);
508 accepted += newAccepted;
510 assert(accepted == length);
518 WritePoststreamTail();
522 Output(0, NULL, 0, messageEnd, blocking);
526 bool Deflator::IsolatedFlush(
bool hardFlush,
bool blocking)
529 throw BlockingInputOnly(
"Deflator");
533 m_minLookahead = MAX_MATCH;
536 EncodeBlock(
false, STORED);
540 void Deflator::LiteralByte(byte b)
542 if (m_matchBufferEnd == m_matchBuffer.size())
545 m_matchBuffer[m_matchBufferEnd++].literalCode = b;
546 m_literalCounts[b]++;
550 void Deflator::MatchFound(
unsigned int distance,
unsigned int length)
552 if (m_matchBufferEnd == m_matchBuffer.size())
555 static const unsigned int lengthCodes[] = {
556 257, 258, 259, 260, 261, 262, 263, 264, 265, 265, 266, 266, 267, 267, 268, 268,
557 269, 269, 269, 269, 270, 270, 270, 270, 271, 271, 271, 271, 272, 272, 272, 272,
558 273, 273, 273, 273, 273, 273, 273, 273, 274, 274, 274, 274, 274, 274, 274, 274,
559 275, 275, 275, 275, 275, 275, 275, 275, 276, 276, 276, 276, 276, 276, 276, 276,
560 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
561 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278,
562 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279,
563 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280,
564 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
565 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
566 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282,
567 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282,
568 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283,
569 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283,
570 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
571 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 285};
572 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};
573 static const unsigned int distanceBases[30] =
574 {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};
576 EncodedMatch &m = m_matchBuffer[m_matchBufferEnd++];
578 unsigned int lengthCode = lengthCodes[length-3];
579 m.literalCode = lengthCode;
580 m.literalExtra = length - lengthBases[lengthCode-257];
581 unsigned int distanceCode = (
unsigned int)(upper_bound(distanceBases, distanceBases+30, distance) - distanceBases - 1);
582 m.distanceCode = distanceCode;
583 m.distanceExtra = distance - distanceBases[distanceCode];
585 m_literalCounts[lengthCode]++;
586 m_distanceCounts[distanceCode]++;
587 m_blockLength += length;
590 inline unsigned int CodeLengthEncode(
const unsigned int *begin,
591 const unsigned int *end,
592 const unsigned int *& p,
593 unsigned int &extraBits,
594 unsigned int &extraBitsLength)
599 const unsigned int *oldp = p;
600 if (v==0 && p[1]==0 && p[2]==0)
602 for (p=p+3; p!=end && *p==0 && p!=oldp+138; p++) {}
603 unsigned int repeat = (
unsigned int)(p - oldp);
606 extraBits = repeat-3;
612 extraBits = repeat-11;
617 else if (p!=begin && v==p[-1] && v==p[1] && v==p[2])
619 for (p=p+3; p!=end && *p==v && p!=oldp+6; p++) {}
620 unsigned int repeat = (
unsigned int)(p - oldp);
621 extraBits = repeat-3;
632 void Deflator::EncodeBlock(
bool eof,
unsigned int blockType)
635 PutBits(blockType, 2);
637 if (blockType == STORED)
639 assert(m_blockStart + m_blockLength <= m_byteBuffer.size());
640 assert(m_blockLength <= 0xffff);
648 if (blockType == DYNAMIC)
650 #if defined(_MSC_VER) && !defined(__MWERKS__) && (_MSC_VER <= 1300)
652 typedef reverse_bidirectional_iterator<unsigned int *, unsigned int> RevIt;
653 #elif defined(_RWSTD_NO_CLASS_PARTIAL_SPEC)
654 typedef reverse_iterator<unsigned int *, random_access_iterator_tag, unsigned int> RevIt;
656 typedef reverse_iterator<unsigned int *> RevIt;
662 m_literalCounts[256] = 1;
663 HuffmanEncoder::GenerateCodeLengths(literalCodeLengths, 15, m_literalCounts, 286);
664 m_dynamicLiteralEncoder.Initialize(literalCodeLengths, 286);
665 unsigned int hlit = (
unsigned int)(find_if(RevIt(literalCodeLengths.end()), RevIt(literalCodeLengths.begin()+257), bind2nd(not_equal_to<unsigned int>(), 0)).base() - (literalCodeLengths.begin()+257));
667 HuffmanEncoder::GenerateCodeLengths(distanceCodeLengths, 15, m_distanceCounts, 30);
668 m_dynamicDistanceEncoder.Initialize(distanceCodeLengths, 30);
669 unsigned int hdist = (
unsigned int)(find_if(RevIt(distanceCodeLengths.end()), RevIt(distanceCodeLengths.begin()+1), bind2nd(not_equal_to<unsigned int>(), 0)).base() - (distanceCodeLengths.begin()+1));
672 memcpy(combinedLengths, literalCodeLengths, (hlit+257)*
sizeof(
unsigned int));
673 memcpy(combinedLengths+hlit+257, distanceCodeLengths, (hdist+1)*
sizeof(
unsigned int));
676 fill(codeLengthCodeCounts.begin(), codeLengthCodeCounts.end(), 0);
677 const unsigned int *p = combinedLengths.begin(), *begin = combinedLengths.begin(), *end = combinedLengths.end();
680 unsigned int code, extraBits, extraBitsLength;
681 code = CodeLengthEncode(begin, end, p, extraBits, extraBitsLength);
682 codeLengthCodeCounts[code]++;
684 HuffmanEncoder::GenerateCodeLengths(codeLengthCodeLengths, 7, codeLengthCodeCounts, 19);
686 static const unsigned int border[] = {
687 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
688 unsigned int hclen = 19;
689 while (hclen > 4 && codeLengthCodeLengths[border[hclen-1]] == 0)
697 for (
unsigned int i=0; i<hclen+4; i++)
698 PutBits(codeLengthCodeLengths[border[i]], 3);
700 p = combinedLengths.begin();
703 unsigned int code, extraBits, extraBitsLength;
704 code = CodeLengthEncode(begin, end, p, extraBits, extraBitsLength);
705 codeLengthEncoder.Encode(*
this, code);
706 PutBits(extraBits, extraBitsLength);
710 static const unsigned int lengthExtraBits[] = {
711 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
712 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0};
713 static const unsigned int distanceExtraBits[] = {
714 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
715 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
718 const HuffmanEncoder &literalEncoder = (blockType == STATIC) ? m_staticLiteralEncoder : m_dynamicLiteralEncoder;
719 const HuffmanEncoder &distanceEncoder = (blockType == STATIC) ? m_staticDistanceEncoder : m_dynamicDistanceEncoder;
721 for (
unsigned int i=0; i<m_matchBufferEnd; i++)
723 unsigned int literalCode = m_matchBuffer[i].literalCode;
724 literalEncoder.Encode(*
this, literalCode);
725 if (literalCode >= 257)
727 assert(literalCode <= 285);
728 PutBits(m_matchBuffer[i].literalExtra, lengthExtraBits[literalCode-257]);
729 unsigned int distanceCode = m_matchBuffer[i].distanceCode;
730 distanceEncoder.Encode(*
this, distanceCode);
731 PutBits(m_matchBuffer[i].distanceExtra, distanceExtraBits[distanceCode]);
734 literalEncoder.Encode(*
this, 256);
738 void Deflator::EndBlock(
bool eof)
740 if (m_blockLength == 0 && !eof)
743 if (m_deflateLevel == 0)
745 EncodeBlock(eof, STORED);
747 if (m_compressibleDeflateLevel > 0 && ++m_detectCount == m_detectSkip)
749 m_deflateLevel = m_compressibleDeflateLevel;
755 unsigned long storedLen = 8*((
unsigned long)m_blockLength+4) + RoundUpToMultipleOf(m_bitsBuffered+3, 8U)-m_bitsBuffered;
758 EncodeBlock(eof, STATIC);
759 unsigned long staticLen = FinishCounting();
761 unsigned long dynamicLen;
762 if (m_blockLength < 128 && m_deflateLevel < 8)
763 dynamicLen = ULONG_MAX;
767 EncodeBlock(eof, DYNAMIC);
768 dynamicLen = FinishCounting();
771 if (storedLen <= staticLen && storedLen <= dynamicLen)
773 EncodeBlock(eof, STORED);
775 if (m_compressibleDeflateLevel > 0)
779 m_detectSkip = m_detectSkip ? STDMIN(2*m_detectSkip, 128U) : 1;
784 if (staticLen <= dynamicLen)
785 EncodeBlock(eof, STATIC);
787 EncodeBlock(eof, DYNAMIC);
789 if (m_compressibleDeflateLevel > 0)
794 m_matchBufferEnd = 0;
795 m_blockStart += m_blockLength;
797 fill(m_literalCounts.begin(), m_literalCounts.end(), 0);
798 fill(m_distanceCounts.begin(), m_distanceCounts.end(), 0);
exception thrown when an invalid argument is detected
a SecBlock that preallocates size S statically, and uses the heap when this size is exceeded ...
T GetValueWithDefault(const char *name, T defaultValue) const
get a named value, returns the default if the name doesn't exist
void New(size_type newSize)
change size, without preserving contents
int GetIntValueWithDefault(const char *name, int defaultValue) const
get a named value with type int, with default
BufferedTransformation * AttachedTransformation()
returns the object immediately attached to this object or NULL for no attachment
void SetDeflateLevel(int deflateLevel)
this function can be used to set the deflate level in the middle of compression
Deflator(BufferedTransformation *attachment=NULL, int deflateLevel=DEFAULT_DEFLATE_LEVEL, int log2WindowSize=DEFAULT_LOG2_WINDOW_SIZE, bool detectUncompressible=true)
provides an implementation of BufferedTransformation's attachment interface
size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
input multiple bytes for blocking or non-blocking processing
interface for retrieving values given their names