22 #include "MCZipper.hpp" 24 #include "MCBinaryData.hpp" 27 #include "MCThreadLocalData.hpp" 28 #include "MCTimer.hpp" 40 #if defined(__MINGW32__) || defined(__MINGW64__) 41 #include <boost/config.hpp> 51 void CheckStaticZipperVariables()
53 if (unlikely(!CompressionBuffer.get()))
56 StateCompress.reset(
new qlz_state_compress);
59 memset(StateCompress.get(), 0,
sizeof(qlz_state_compress));
60 StateDecompress.reset(
new qlz_state_decompress);
63 memset(StateDecompress.get(), 0,
sizeof(qlz_state_decompress));
70 const StringList CompressionTypeStrs = {
"Invalid",
"Lz4",
"Zlib",
"QuickLZ",
"MiniLzo",
"Shrinker",
72 const StringList CompressionLevelTypeStrs = {
"Fast",
"Medium",
"Best"};
77 CheckStaticZipperVariables();
83 int CompressedSize = 0;
84 std::string IdStr = MC::CompressionTypeStrs[(int)MC::QuickLzCompression];
86 if (CompressionBuffer->GetSize() < input_buffer.
GetSize()+400+(int)IdStr.size())
88 CompressionBuffer->Allocate(input_buffer.
GetSize()+400+IdStr.size());
90 CompressedSize = qlz_compress((
char*)input_buffer.
GetData(), (
char*)CompressionBuffer->GetData(),
91 input_buffer.
GetSize(), &*StateCompress);
92 int FinalSize = CompressedSize+(int)IdStr.size()+4;
94 if (output_buffer.
GetSize() != FinalSize)
100 memcpy((
char*)&output_buffer.
GetData()[4], IdStr.c_str(), IdStr.size());
101 memcpy((
char*)&output_buffer.
GetData()[IdStr.size()+4], (
char*)CompressionBuffer->GetData(),
109 if (!without_header && DetectCompressionMethod(input_buffer) != MC::QuickLzCompression)
112 CheckStaticZipperVariables();
113 std::string IdStr = MC::CompressionTypeStrs[(int)MC::QuickLzCompression];
114 char* DataStart = !without_header ? (
char*)&input_buffer.
GetData()[IdStr.size()+4] :
116 int DecompressedSize = qlz_size_decompressed(DataStart);
127 if (PacketSize != input_buffer.
GetSize())
130 if (output_buffer.
GetSize() != DecompressedSize)
132 output_buffer.
Allocate(DecompressedSize);
134 qlz_decompress(DataStart, (
char*)output_buffer.
GetData(), &*StateDecompress);
140 CheckStaticZipperVariables();
141 std::string IdStr = MC::CompressionTypeStrs[(int)MC::Lz4Compression];
142 int BufferSize = LZ4_compressBound(input_buffer.
GetSize());
144 if (CompressionBuffer->GetSize() < BufferSize)
146 CompressionBuffer->Allocate(BufferSize);
148 int OriginalSize = input_buffer.
GetSize();
149 int CompressedSize = LZ4_compress((
char*)input_buffer.
GetData(), (
char*)CompressionBuffer->GetData(),
151 int FinalSize = CompressedSize+(int)IdStr.size()+12;
153 if (output_buffer.
GetSize() != FinalSize)
159 memcpy((
char*)&output_buffer.
GetData()[4], IdStr.c_str(), IdStr.size());
161 output_buffer.
AddInt32(OriginalSize);
162 output_buffer.
AddInt32(CompressedSize);
163 memcpy((
char*)&output_buffer.
GetData()[IdStr.size()+12], (
char*)CompressionBuffer->GetData(),
170 if (DetectCompressionMethod(input_buffer) != MC::Lz4Compression)
173 CheckStaticZipperVariables();
174 std::string IdStr = MC::CompressionTypeStrs[(int)MC::Lz4Compression];
178 int OriginalSize = 0;
179 int CompressedSize = 0;
181 Packet.SetPosition(0);
182 PacketSize = Packet.GetInt32();
183 Packet.IncrementPosition(IdStr.size());
184 OriginalSize = Packet.GetInt32();
185 CompressedSize = Packet.GetInt32();
186 Packet.SetPosition(OldPosition);
187 if (PacketSize != input_buffer.
GetSize() || OriginalSize <= 0 ||
188 CompressedSize+12+(int)IdStr.size() != input_buffer.
GetSize())
192 if (CompressionBuffer->GetSize() < OriginalSize)
194 CompressionBuffer->Allocate(OriginalSize);
196 int Result = LZ4_decompress_safe((
char*)&input_buffer.
GetData()[IdStr.size()+12],
197 (
char*)CompressionBuffer->GetData(),
198 input_buffer.
GetSize()-IdStr.size()-12, CompressionBuffer->GetSize());
200 if (Result != OriginalSize)
202 if (output_buffer.
GetSize() != Result)
206 memcpy(output_buffer.
GetData(), CompressionBuffer->GetData(), Result);
212 CheckStaticZipperVariables();
213 std::string IdStr = MC::CompressionTypeStrs[(int)MC::MiniLzoCompression];
214 int BufferSize = (int)input_buffer.
GetSize()*11 / 10+100;
216 output_buffer.
Allocate((
int)LZO1X_1_MEM_COMPRESS);
217 if (CompressionBuffer->GetSize() < BufferSize)
219 CompressionBuffer->Allocate(BufferSize);
223 lzo_uint OutputBufferSize = (lzo_uint)output_buffer.
GetSize();
224 int Result = lzo1x_1_compress((lzo_bytep)input_buffer.
GetData(), (lzo_uint)input_buffer.
GetSize(),
225 (lzo_bytep)CompressionBuffer->GetData(), (lzo_uintp)&OutputBufferSize,
226 (lzo_voidp)output_buffer.
GetData());
228 if (Result == LZO_E_OK)
230 int FinalSize = (int)OutputBufferSize+(
int)IdStr.size()+8;
231 int OriginalSize = input_buffer.
GetSize();
233 if (output_buffer.
GetSize() != FinalSize)
239 memcpy((
char*)&output_buffer.
GetData()[4], IdStr.c_str(), IdStr.size());
241 output_buffer.
AddInt32(OriginalSize);
242 memcpy((
char*)&output_buffer.
GetData()[IdStr.size()+8], (
char*)CompressionBuffer->GetData(),
243 (int)OutputBufferSize);
250 if (DetectCompressionMethod(input_buffer) != MC::MiniLzoCompression)
253 CheckStaticZipperVariables();
254 std::string IdStr = MC::CompressionTypeStrs[(int)MC::MiniLzoCompression];
258 int OriginalSize = 0;
260 Packet.SetPosition(0);
261 PacketSize = Packet.GetInt32();
262 Packet.IncrementPosition(IdStr.size());
263 OriginalSize = Packet.GetInt32();
264 Packet.SetPosition(OldPosition);
265 if (PacketSize != input_buffer.
GetSize() || OriginalSize <= 0)
268 if (CompressionBuffer->GetSize() < OriginalSize)
270 CompressionBuffer->Allocate(OriginalSize);
272 lzo_uint FinalSize = CompressionBuffer->GetSize();
273 int Result = lzo1x_decompress_safe((lzo_bytep)&input_buffer.
GetData()[IdStr.size()+8],
274 (lzo_uint)(input_buffer.
GetSize()-IdStr.size()-8),
275 (lzo_bytep)CompressionBuffer->GetData(), (lzo_uintp)&FinalSize,
278 if (Result != LZO_E_OK)
280 if (output_buffer.
GetSize() != (int)FinalSize)
282 output_buffer.
Allocate((
int)FinalSize);
284 memcpy(output_buffer.
GetData(), CompressionBuffer->GetData(), (int)FinalSize);
290 CheckStaticZipperVariables();
291 std::string IdStr = MC::CompressionTypeStrs[(int)MC::ShrinkerCompression];
293 if (CompressionBuffer->GetSize() < input_buffer.
GetSize()+200)
295 CompressionBuffer->Allocate(input_buffer.
GetSize()+200);
297 int Result = shrinker_compress((
char*)input_buffer.
GetData(), (
char*)CompressionBuffer->GetData(),
302 int FinalSize = Result+(int)IdStr.size()+8;
303 int OriginalSize = input_buffer.
GetSize();
305 if (output_buffer.
GetSize() != FinalSize)
311 memcpy((
char*)&output_buffer.
GetData()[4], IdStr.c_str(), IdStr.size());
313 output_buffer.
AddInt32(OriginalSize);
314 memcpy((
char*)&output_buffer.
GetData()[IdStr.size()+8], (
char*)CompressionBuffer->GetData(), Result);
321 if (DetectCompressionMethod(input_buffer) != MC::ShrinkerCompression)
324 CheckStaticZipperVariables();
325 std::string IdStr = MC::CompressionTypeStrs[(int)MC::ShrinkerCompression];
329 int OriginalSize = 0;
331 Packet.SetPosition(0);
332 PacketSize = Packet.GetInt32();
333 Packet.IncrementPosition(IdStr.size());
334 OriginalSize = Packet.GetInt32();
335 Packet.SetPosition(OldPosition);
336 if (PacketSize != input_buffer.
GetSize() || input_buffer.
GetSize() < 36+(int)IdStr.size()+8 ||
341 if (output_buffer.
GetSize() < OriginalSize)
343 output_buffer.
Allocate(OriginalSize);
345 shrinker_decompress(&input_buffer.
GetData()[IdStr.size()+8], output_buffer.
GetData());
351 CheckStaticZipperVariables();
352 std::string IdStr = MC::CompressionTypeStrs[(int)MC::SnappyCompression];
353 size_t BufferSize = (int)snappy::MaxCompressedLength((
size_t)input_buffer.
GetSize())+IdStr.size();
355 if (CompressionBuffer->GetSize() < (int)BufferSize)
357 CompressionBuffer->Allocate((
int)BufferSize);
359 BufferSize = (size_t)CompressionBuffer->GetSize();
361 snappy::RawCompress((
char*)input_buffer.
GetData(), (size_t)input_buffer.
GetSize(),
362 (
char*)CompressionBuffer->GetData(), &BufferSize);
363 int FinalSize = (int)BufferSize+(
int)IdStr.size()+8;
365 if (output_buffer.
GetSize() != FinalSize)
371 memcpy((
char*)&output_buffer.
GetData()[4], IdStr.c_str(), IdStr.size());
372 memcpy((
char*)&output_buffer.
GetData()[IdStr.size()+4], (
char*)CompressionBuffer->GetData(),
379 if (DetectCompressionMethod(input_buffer) != MC::SnappyCompression)
382 CheckStaticZipperVariables();
383 std::string IdStr = MC::CompressionTypeStrs[(int)MC::SnappyCompression];
388 Packet.SetPosition(0);
389 PacketSize = Packet.GetInt32();
390 Packet.SetPosition(OldPosition);
391 if (PacketSize != input_buffer.
GetSize())
394 size_t DecompressedSize = 0;
396 if (snappy::GetUncompressedLength((
char*)&input_buffer.
GetData()[IdStr.size()+4],
397 (size_t)(input_buffer.
GetSize()-IdStr.size()-4),
400 if (output_buffer.
GetSize() != (int)DecompressedSize)
402 output_buffer.
Allocate((
int)DecompressedSize);
404 snappy::RawUncompress((
char*)&input_buffer.
GetData()[IdStr.size()+4],
405 (size_t)(input_buffer.
GetSize()-IdStr.size()-4),
406 (
char*)output_buffer.
GetData());
412 MC::CompressionLevelsType compression_level)
414 CheckStaticZipperVariables();
415 std::string IdStr = MC::CompressionTypeStrs[(int)MC::ZlibCompression];
416 uLong BufferSize = compressBound((uLong)input_buffer.
GetSize())+IdStr.size()+8;
418 if (CompressionBuffer->GetSize() < (int)BufferSize)
420 CompressionBuffer->Allocate((
int)BufferSize);
422 uLongf OutputBufferSize = (uLongf)CompressionBuffer->GetSize();
423 int CompressionLevel = compression_level == MC::BestCompression ? Z_BEST_COMPRESSION :
424 (compression_level == MC::MediumCompression ? Z_DEFAULT_COMPRESSION :
426 compress2((Bytef*)CompressionBuffer->GetData(), &OutputBufferSize, (Bytef*)input_buffer.
GetData(),
427 (uLong)input_buffer.
GetSize(), CompressionLevel);
428 int FinalSize = (int)OutputBufferSize+(
int)IdStr.size()+8;
429 int OriginalSize = input_buffer.
GetSize();
431 if (output_buffer.
GetSize() != FinalSize)
433 output_buffer.
Allocate((
int)FinalSize);
437 memcpy((
char*)&output_buffer.
GetData()[4], IdStr.c_str(), IdStr.size());
439 output_buffer.
AddInt32(OriginalSize);
440 memcpy((
char*)&output_buffer.
GetData()[IdStr.size()+8], (
char*)CompressionBuffer->GetData(),
441 (int)OutputBufferSize);
447 if (DetectCompressionMethod(input_buffer) != MC::ZlibCompression)
450 CheckStaticZipperVariables();
451 std::string IdStr = MC::CompressionTypeStrs[(int)MC::ZlibCompression];
455 int OriginalSize = 0;
457 Packet.SetPosition(0);
458 PacketSize = Packet.GetInt32();
459 Packet.IncrementPosition(IdStr.size());
460 OriginalSize = Packet.GetInt32();
461 Packet.SetPosition(OldPosition);
462 if (PacketSize != input_buffer.
GetSize() || OriginalSize <= 0)
464 if (CompressionBuffer->GetSize() < OriginalSize)
466 CompressionBuffer->Allocate(OriginalSize);
468 uLongf FinalSize = (uLongf)CompressionBuffer->GetSize();
469 int Result = uncompress((Bytef*)CompressionBuffer->GetData(), &FinalSize,
470 (Bytef*)&input_buffer.
GetData()[IdStr.size()+8],
471 (uLong)(input_buffer.
GetSize()-IdStr.size()-8));
475 output_buffer.
Allocate((
int)FinalSize);
476 memcpy(output_buffer.
GetData(), CompressionBuffer->GetData(), (int)FinalSize);
482 MC::CompressionLevelsType compression_level)
484 CheckStaticZipperVariables();
485 std::string IdStr = MC::CompressionTypeStrs[(int)MC::Bzip2Compression];
486 unsigned int BufferSize = input_buffer.
GetSize()*105 / 100+700;
488 if (CompressionBuffer->GetSize() < (int)BufferSize)
490 CompressionBuffer->Allocate((
int)BufferSize);
492 int CompressionLevel = compression_level == MC::BestCompression ? 9 :
493 (compression_level == MC::MediumCompression ? 5 : 1);
495 BZ2_bzBuffToBuffCompress((
char*)CompressionBuffer->GetData(), &BufferSize,
497 CompressionLevel, 0, 0);
498 int FinalSize = (int)BufferSize+(
int)IdStr.size()+8;
499 int OriginalSize = input_buffer.
GetSize();
501 if (output_buffer.
GetSize() != FinalSize)
507 memcpy((
char*)&output_buffer.
GetData()[4], IdStr.c_str(), IdStr.size());
509 output_buffer.
AddInt32(OriginalSize);
510 memcpy((
char*)&output_buffer.
GetData()[IdStr.size()+8], (
char*)CompressionBuffer->GetData(),
517 if (DetectCompressionMethod(input_buffer) != MC::Bzip2Compression)
520 CheckStaticZipperVariables();
521 std::string IdStr = MC::CompressionTypeStrs[(int)MC::Bzip2Compression];
525 int OriginalSize = 0;
527 Packet.SetPosition(0);
528 PacketSize = Packet.GetInt32();
529 Packet.IncrementPosition(IdStr.size());
530 OriginalSize = Packet.GetInt32();
531 Packet.SetPosition(OldPosition);
532 if (PacketSize != input_buffer.
GetSize() || OriginalSize <= 0)
534 if (CompressionBuffer->GetSize() < OriginalSize)
536 CompressionBuffer->Allocate(OriginalSize);
538 unsigned int DecompressedSize = CompressionBuffer->GetSize();
539 int Result = BZ2_bzBuffToBuffDecompress((
char*)CompressionBuffer->GetData(), &DecompressedSize,
540 (
char*)&input_buffer.
GetData()[IdStr.size()+8],
541 input_buffer.
GetSize()-IdStr.size()-8, 0, 0);
545 output_buffer.
Allocate((
int)DecompressedSize);
546 memcpy(output_buffer.
GetData(), CompressionBuffer->GetData(), (int)DecompressedSize);
555 MC::CompressionDescriptor BestCompression;
560 BestCompression.second = MC::MediumCompression;
561 for (
int i = (
int)MC::Lz4Compression; i <= (int)MC::Bzip2Compression; ++i)
563 for (
int i1 = (
int)MC::FastCompression; i1 <= (int)MC::BestCompression; ++i1)
565 if ((i1 == (
int)MC::FastCompression || i1 == (int)MC::BestCompression) &&
566 i != (int)MC::Bzip2Compression && i != (
int)MC::ZlibCompression)
571 if (i == (
int)MC::Lz4Compression)
572 CompressLz4(input_buffer, *TempBuffer);
573 if (i == (
int)MC::ZlibCompression)
574 CompressZlib(input_buffer, *TempBuffer, (MC::CompressionLevelsType)i1);
575 if (i == (
int)MC::QuickLzCompression)
576 CompressQuickLz(input_buffer, *TempBuffer);
577 if (i == (
int)MC::MiniLzoCompression)
578 CompressMiniLzo(input_buffer, *TempBuffer);
579 if (i == (
int)MC::ShrinkerCompression)
580 CompressShrinker(input_buffer, *TempBuffer);
581 if (i == (
int)MC::SnappyCompression)
582 CompressSnappy(input_buffer, *TempBuffer);
583 if (i == (
int)MC::Bzip2Compression)
584 CompressBzip2(input_buffer, *TempBuffer, (MC::CompressionLevelsType)i1);
590 MC_LOG(
"Compression size and speed (%s/%s): %d bytes, %d bytes / msec",
591 MC::CompressionTypeStrs[i].c_str(), MC::CompressionLevelTypeStrs[i1].c_str(),
592 TempBuffer->GetSize(),
595 if (i == (
int)MC::Lz4Compression)
596 DecompressLz4(*TempBuffer, *TempBuffer2);
597 if (i == (
int)MC::ZlibCompression)
598 DecompressZlib(*TempBuffer, *TempBuffer2);
599 if (i == (
int)MC::QuickLzCompression)
600 DecompressQuickLz(*TempBuffer, *TempBuffer2);
601 if (i == (
int)MC::MiniLzoCompression)
602 DecompressMiniLzo(*TempBuffer, *TempBuffer2);
603 if (i == (
int)MC::ShrinkerCompression)
604 DecompressShrinker(*TempBuffer, *TempBuffer2);
605 if (i == (
int)MC::SnappyCompression)
606 DecompressSnappy(*TempBuffer, *TempBuffer2);
607 if (i == (
int)MC::Bzip2Compression)
608 DecompressBzip2(*TempBuffer, *TempBuffer2);
611 ElapsedTime = (ElapsedTime > 0 ? ElapsedTime : 1);
612 MC_LOG(
"Decompression speed (%s/%s): %d bytes / msec",
613 MC::CompressionTypeStrs[i].c_str(), MC::CompressionLevelTypeStrs[i1].c_str(),
614 (
int)((int64_t)input_buffer.
GetSize()*1000 / ElapsedTime));
616 if (i == (
int)MC::Lz4Compression || TempBuffer->GetSize() < output_buffer.
GetSize())
618 output_buffer = std::move(*TempBuffer);
619 BestCompression.first = (MC::CompressionsType)i;
620 BestCompression.second = (MC::CompressionLevelsType)i1;
624 return BestCompression;
629 MC::CompressionsType compression)
631 if (input_buffer.
GetSize() < 4)
632 return MC::InvalidCompression;
641 if (Size < 0 || Size > input_buffer.
GetSize())
642 return MC::InvalidCompression;
643 for (
int i = (
int)MC::Lz4Compression; i <= (int)MC::Bzip2Compression; ++i)
646 if (compression != MC::InvalidCompression && compression != (MC::CompressionsType)i)
649 std::string IdStr = MC::CompressionTypeStrs[(MC::CompressionsType)i];
651 if (input_buffer.
GetSize() < (int)IdStr.size()+4)
655 for (
unsigned int i1 = 0; i1 < IdStr.size(); ++i1)
657 if (IdStr.c_str()[i1] != input_buffer.
GetData()[i1+4])
664 return (MC::CompressionsType)i;
666 return MC::InvalidCompression;
672 CheckStaticZipperVariables();
673 CompressionBuffer->Allocate(10000);
void Start(int time_shift=0)
Start the timer.
static void DecompressSnappy(const MCBinaryData &input_buffer, MCBinaryData &output_buffer)
Decompress data with snappy algorithm.
static void CompressShrinker(const MCBinaryData &input_buffer, MCBinaryData &output_buffer)
Compress data with shrinker algorithm.
static void ReleaseCache()
Release the allocated temporal compression cache.
static void DecompressMiniLzo(const MCBinaryData &input_buffer, MCBinaryData &output_buffer)
Decompress data with minilzo algorithm.
static void DecompressLz4(const MCBinaryData &input_buffer, MCBinaryData &output_buffer)
Decompress data with lz4 algorithm.
static MC::CompressionDescriptor FindBestCompression(const MCBinaryData &input_buffer, MCBinaryData &output_buffer, bool test_mode=false)
Find the best compression.
void Allocate(int size)
Allocate a certain data size.
static void DecompressShrinker(const MCBinaryData &input_buffer, MCBinaryData &output_buffer)
Decompress data with shrinker algorithm.
void AddInt32(int32_t new_int, bool reverse_order=false)
Add a 32 bit integer at the current position.
static void CompressLz4(const MCBinaryData &input_buffer, MCBinaryData &output_buffer)
Compress data with lz4 algorithm.
static void DecompressQuickLz(const MCBinaryData &input_buffer, MCBinaryData &output_buffer, bool without_header=false)
Decompress data with QuickLZ algorithm.
void SetPosition(unsigned int position)
Set the cursor position.
void IncrementPosition(unsigned int position=1)
Increment the cursor position.
static void CompressMiniLzo(const MCBinaryData &input_buffer, MCBinaryData &output_buffer)
Compress data with minilzo algorithm.
static void DecompressZlib(const MCBinaryData &input_buffer, MCBinaryData &output_buffer)
Decompress data with zlib algorithm.
unsigned char * GetData() const
Get direct access to the binary data.
Simple timer class with microsecond precision.
int64_t GetElapsedTimeInUSecs()
Get the elapsed time in microseconds since the timer has been started or since the last timeout...
static void CompressBzip2(const MCBinaryData &input_buffer, MCBinaryData &output_buffer, MC::CompressionLevelsType compression_level)
Compress data with bzip2 algorithm.
int32_t GetInt32(bool reverse_order=false)
Get a 32 bit integer from the current position.
A wrapper class to cover boost::thread_specific_ptr/folly::ThreadLocal API on certain targets...
static MC::CompressionsType DetectCompressionMethod(const MCBinaryData &input_buffer, MC::CompressionsType compression=MC::InvalidCompression)
Detect the compression method of a buffer.
static void CompressSnappy(const MCBinaryData &input_buffer, MCBinaryData &output_buffer)
Compress data with snappy algorithm.
#define MC_LOG(...)
Debug macro.
static void CompressZlib(const MCBinaryData &input_buffer, MCBinaryData &output_buffer, MC::CompressionLevelsType compression_level)
Compress data with zlib algorithm.
static void DecompressBzip2(const MCBinaryData &input_buffer, MCBinaryData &output_buffer)
Decompress data with bzip2 algorithm.
int GetPosition() const
Get the current position in the binary data.
static void CompressQuickLz(const MCBinaryData &input_buffer, MCBinaryData &output_buffer)
Compress data with QuickLZ algorithm.
int GetSize() const
Get binary data size.