12fb337e7SAlexey Samsonov //===--- Compression.cpp - Compression implementation ---------------------===// 22fb337e7SAlexey Samsonov // 32fb337e7SAlexey Samsonov // The LLVM Compiler Infrastructure 42fb337e7SAlexey Samsonov // 52fb337e7SAlexey Samsonov // This file is distributed under the University of Illinois Open Source 62fb337e7SAlexey Samsonov // License. See LICENSE.TXT for details. 72fb337e7SAlexey Samsonov // 82fb337e7SAlexey Samsonov //===----------------------------------------------------------------------===// 92fb337e7SAlexey Samsonov // 102fb337e7SAlexey Samsonov // This file implements compression functions. 112fb337e7SAlexey Samsonov // 122fb337e7SAlexey Samsonov //===----------------------------------------------------------------------===// 132fb337e7SAlexey Samsonov 142fb337e7SAlexey Samsonov #include "llvm/Support/Compression.h" 152fb337e7SAlexey Samsonov #include "llvm/ADT/OwningPtr.h" 162fb337e7SAlexey Samsonov #include "llvm/ADT/StringRef.h" 172fb337e7SAlexey Samsonov #include "llvm/Config/config.h" 180c9f1bfaSAlexey Samsonov #include "llvm/Support/Compiler.h" 192fb337e7SAlexey Samsonov #include "llvm/Support/ErrorHandling.h" 202fb337e7SAlexey Samsonov #include "llvm/Support/MemoryBuffer.h" 212fb337e7SAlexey Samsonov #if LLVM_ENABLE_ZLIB == 1 && HAVE_ZLIB_H 222fb337e7SAlexey Samsonov #include <zlib.h> 232fb337e7SAlexey Samsonov #endif 242fb337e7SAlexey Samsonov 252fb337e7SAlexey Samsonov using namespace llvm; 262fb337e7SAlexey Samsonov 2728acf056SAlexey Samsonov #if LLVM_ENABLE_ZLIB == 1 && HAVE_LIBZ 282fb337e7SAlexey Samsonov static int encodeZlibCompressionLevel(zlib::CompressionLevel Level) { 292fb337e7SAlexey Samsonov switch (Level) { 302fb337e7SAlexey Samsonov case zlib::NoCompression: return 0; 312fb337e7SAlexey Samsonov case zlib::BestSpeedCompression: return 1; 322fb337e7SAlexey Samsonov case zlib::DefaultCompression: return Z_DEFAULT_COMPRESSION; 332fb337e7SAlexey Samsonov case zlib::BestSizeCompression: return 9; 342fb337e7SAlexey Samsonov } 3563761d4bSHans Wennborg llvm_unreachable("Invalid zlib::CompressionLevel!"); 362fb337e7SAlexey Samsonov } 372fb337e7SAlexey Samsonov 382fb337e7SAlexey Samsonov static zlib::Status encodeZlibReturnValue(int ReturnValue) { 392fb337e7SAlexey Samsonov switch (ReturnValue) { 402fb337e7SAlexey Samsonov case Z_OK: return zlib::StatusOK; 412fb337e7SAlexey Samsonov case Z_MEM_ERROR: return zlib::StatusOutOfMemory; 422fb337e7SAlexey Samsonov case Z_BUF_ERROR: return zlib::StatusBufferTooShort; 432fb337e7SAlexey Samsonov case Z_STREAM_ERROR: return zlib::StatusInvalidArg; 442fb337e7SAlexey Samsonov case Z_DATA_ERROR: return zlib::StatusInvalidData; 452fb337e7SAlexey Samsonov default: llvm_unreachable("unknown zlib return status!"); 462fb337e7SAlexey Samsonov } 472fb337e7SAlexey Samsonov } 482fb337e7SAlexey Samsonov 492fb337e7SAlexey Samsonov bool zlib::isAvailable() { return true; } 502fb337e7SAlexey Samsonov zlib::Status zlib::compress(StringRef InputBuffer, 512fb337e7SAlexey Samsonov OwningPtr<MemoryBuffer> &CompressedBuffer, 522fb337e7SAlexey Samsonov CompressionLevel Level) { 532fb337e7SAlexey Samsonov unsigned long CompressedSize = ::compressBound(InputBuffer.size()); 542fb337e7SAlexey Samsonov OwningArrayPtr<char> TmpBuffer(new char[CompressedSize]); 552fb337e7SAlexey Samsonov int CLevel = encodeZlibCompressionLevel(Level); 562fb337e7SAlexey Samsonov Status Res = encodeZlibReturnValue(::compress2( 572fb337e7SAlexey Samsonov (Bytef *)TmpBuffer.get(), &CompressedSize, 582fb337e7SAlexey Samsonov (const Bytef *)InputBuffer.data(), InputBuffer.size(), CLevel)); 590c9f1bfaSAlexey Samsonov if (Res == StatusOK) { 602fb337e7SAlexey Samsonov CompressedBuffer.reset(MemoryBuffer::getMemBufferCopy( 612fb337e7SAlexey Samsonov StringRef(TmpBuffer.get(), CompressedSize))); 620c9f1bfaSAlexey Samsonov // Tell MSan that memory initialized by zlib is valid. 63*fdcff04aSAlexey Samsonov __msan_unpoison(CompressedBuffer->getBufferStart(), CompressedSize); 640c9f1bfaSAlexey Samsonov } 652fb337e7SAlexey Samsonov return Res; 662fb337e7SAlexey Samsonov } 672fb337e7SAlexey Samsonov 682fb337e7SAlexey Samsonov zlib::Status zlib::uncompress(StringRef InputBuffer, 692fb337e7SAlexey Samsonov OwningPtr<MemoryBuffer> &UncompressedBuffer, 702fb337e7SAlexey Samsonov size_t UncompressedSize) { 712fb337e7SAlexey Samsonov OwningArrayPtr<char> TmpBuffer(new char[UncompressedSize]); 722fb337e7SAlexey Samsonov Status Res = encodeZlibReturnValue( 732fb337e7SAlexey Samsonov ::uncompress((Bytef *)TmpBuffer.get(), (uLongf *)&UncompressedSize, 742fb337e7SAlexey Samsonov (const Bytef *)InputBuffer.data(), InputBuffer.size())); 750c9f1bfaSAlexey Samsonov if (Res == StatusOK) { 762fb337e7SAlexey Samsonov UncompressedBuffer.reset(MemoryBuffer::getMemBufferCopy( 772fb337e7SAlexey Samsonov StringRef(TmpBuffer.get(), UncompressedSize))); 780c9f1bfaSAlexey Samsonov // Tell MSan that memory initialized by zlib is valid. 79*fdcff04aSAlexey Samsonov __msan_unpoison(UncompressedBuffer->getBufferStart(), UncompressedSize); 800c9f1bfaSAlexey Samsonov } 812fb337e7SAlexey Samsonov return Res; 822fb337e7SAlexey Samsonov } 832fb337e7SAlexey Samsonov 842fb337e7SAlexey Samsonov #else 852fb337e7SAlexey Samsonov bool zlib::isAvailable() { return false; } 862fb337e7SAlexey Samsonov zlib::Status zlib::compress(StringRef InputBuffer, 872fb337e7SAlexey Samsonov OwningPtr<MemoryBuffer> &CompressedBuffer, 882fb337e7SAlexey Samsonov CompressionLevel Level) { 892fb337e7SAlexey Samsonov return zlib::StatusUnsupported; 902fb337e7SAlexey Samsonov } 912fb337e7SAlexey Samsonov zlib::Status zlib::uncompress(StringRef InputBuffer, 922fb337e7SAlexey Samsonov OwningPtr<MemoryBuffer> &UncompressedBuffer, 932fb337e7SAlexey Samsonov size_t UncompressedSize) { 942fb337e7SAlexey Samsonov return zlib::StatusUnsupported; 952fb337e7SAlexey Samsonov } 962fb337e7SAlexey Samsonov #endif 972fb337e7SAlexey Samsonov 98