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" 1516132e6fSBenjamin Kramer #include "llvm/ADT/SmallVector.h" 162fb337e7SAlexey Samsonov #include "llvm/ADT/StringRef.h" 172fb337e7SAlexey Samsonov #include "llvm/Config/config.h" 180c9f1bfaSAlexey Samsonov #include "llvm/Support/Compiler.h" 19167ca4aeSGeorge Rimar #include "llvm/Support/Error.h" 202fb337e7SAlexey Samsonov #include "llvm/Support/ErrorHandling.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 28167ca4aeSGeorge Rimar static Error createError(StringRef Err) { 29167ca4aeSGeorge Rimar return make_error<StringError>(Err, inconvertibleErrorCode()); 30167ca4aeSGeorge Rimar } 31167ca4aeSGeorge Rimar 322fb337e7SAlexey Samsonov static int encodeZlibCompressionLevel(zlib::CompressionLevel Level) { 332fb337e7SAlexey Samsonov switch (Level) { 342fb337e7SAlexey Samsonov case zlib::NoCompression: return 0; 352fb337e7SAlexey Samsonov case zlib::BestSpeedCompression: return 1; 362fb337e7SAlexey Samsonov case zlib::DefaultCompression: return Z_DEFAULT_COMPRESSION; 372fb337e7SAlexey Samsonov case zlib::BestSizeCompression: return 9; 382fb337e7SAlexey Samsonov } 3963761d4bSHans Wennborg llvm_unreachable("Invalid zlib::CompressionLevel!"); 402fb337e7SAlexey Samsonov } 412fb337e7SAlexey Samsonov 42167ca4aeSGeorge Rimar static StringRef convertZlibCodeToString(int Code) { 43167ca4aeSGeorge Rimar switch (Code) { 44167ca4aeSGeorge Rimar case Z_MEM_ERROR: 45167ca4aeSGeorge Rimar return "zlib error: Z_MEM_ERROR"; 46167ca4aeSGeorge Rimar case Z_BUF_ERROR: 47167ca4aeSGeorge Rimar return "zlib error: Z_BUF_ERROR"; 48167ca4aeSGeorge Rimar case Z_STREAM_ERROR: 49167ca4aeSGeorge Rimar return "zlib error: Z_STREAM_ERROR"; 50167ca4aeSGeorge Rimar case Z_DATA_ERROR: 51167ca4aeSGeorge Rimar return "zlib error: Z_DATA_ERROR"; 52167ca4aeSGeorge Rimar case Z_OK: 53167ca4aeSGeorge Rimar default: 54167ca4aeSGeorge Rimar llvm_unreachable("unknown or unexpected zlib status code"); 552fb337e7SAlexey Samsonov } 562fb337e7SAlexey Samsonov } 572fb337e7SAlexey Samsonov 582fb337e7SAlexey Samsonov bool zlib::isAvailable() { return true; } 59167ca4aeSGeorge Rimar 60167ca4aeSGeorge Rimar Error zlib::compress(StringRef InputBuffer, 61857497b9SDavid Blaikie SmallVectorImpl<char> &CompressedBuffer, 622fb337e7SAlexey Samsonov CompressionLevel Level) { 632fb337e7SAlexey Samsonov unsigned long CompressedSize = ::compressBound(InputBuffer.size()); 64*23310a89SFangrui Song CompressedBuffer.reserve(CompressedSize); 652fb337e7SAlexey Samsonov int CLevel = encodeZlibCompressionLevel(Level); 66167ca4aeSGeorge Rimar int Res = ::compress2((Bytef *)CompressedBuffer.data(), &CompressedSize, 67167ca4aeSGeorge Rimar (const Bytef *)InputBuffer.data(), InputBuffer.size(), 68167ca4aeSGeorge Rimar CLevel); 6928cacae2SEvgeniy Stepanov // Tell MemorySanitizer that zlib output buffer is fully initialized. 7028cacae2SEvgeniy Stepanov // This avoids a false report when running LLVM with uninstrumented ZLib. 7128cacae2SEvgeniy Stepanov __msan_unpoison(CompressedBuffer.data(), CompressedSize); 72*23310a89SFangrui Song CompressedBuffer.set_size(CompressedSize); 73167ca4aeSGeorge Rimar return Res ? createError(convertZlibCodeToString(Res)) : Error::success(); 742fb337e7SAlexey Samsonov } 752fb337e7SAlexey Samsonov 76167ca4aeSGeorge Rimar Error zlib::uncompress(StringRef InputBuffer, char *UncompressedBuffer, 7746cdcb03SRafael Espindola size_t &UncompressedSize) { 78167ca4aeSGeorge Rimar int Res = 7946cdcb03SRafael Espindola ::uncompress((Bytef *)UncompressedBuffer, (uLongf *)&UncompressedSize, 80167ca4aeSGeorge Rimar (const Bytef *)InputBuffer.data(), InputBuffer.size()); 8146cdcb03SRafael Espindola // Tell MemorySanitizer that zlib output buffer is fully initialized. 8246cdcb03SRafael Espindola // This avoids a false report when running LLVM with uninstrumented ZLib. 8346cdcb03SRafael Espindola __msan_unpoison(UncompressedBuffer, UncompressedSize); 84167ca4aeSGeorge Rimar return Res ? createError(convertZlibCodeToString(Res)) : Error::success(); 8546cdcb03SRafael Espindola } 8646cdcb03SRafael Espindola 87167ca4aeSGeorge Rimar Error zlib::uncompress(StringRef InputBuffer, 88a505f247SDavid Blaikie SmallVectorImpl<char> &UncompressedBuffer, 892fb337e7SAlexey Samsonov size_t UncompressedSize) { 90a505f247SDavid Blaikie UncompressedBuffer.resize(UncompressedSize); 91167ca4aeSGeorge Rimar Error E = 9246cdcb03SRafael Espindola uncompress(InputBuffer, UncompressedBuffer.data(), UncompressedSize); 93a505f247SDavid Blaikie UncompressedBuffer.resize(UncompressedSize); 94167ca4aeSGeorge Rimar return E; 952fb337e7SAlexey Samsonov } 962fb337e7SAlexey Samsonov 976ede706dSAlexey Samsonov uint32_t zlib::crc32(StringRef Buffer) { 986ede706dSAlexey Samsonov return ::crc32(0, (const Bytef *)Buffer.data(), Buffer.size()); 996ede706dSAlexey Samsonov } 1006ede706dSAlexey Samsonov 1012fb337e7SAlexey Samsonov #else 1022fb337e7SAlexey Samsonov bool zlib::isAvailable() { return false; } 103167ca4aeSGeorge Rimar Error zlib::compress(StringRef InputBuffer, 104857497b9SDavid Blaikie SmallVectorImpl<char> &CompressedBuffer, 1052fb337e7SAlexey Samsonov CompressionLevel Level) { 106167ca4aeSGeorge Rimar llvm_unreachable("zlib::compress is unavailable"); 1072fb337e7SAlexey Samsonov } 108167ca4aeSGeorge Rimar Error zlib::uncompress(StringRef InputBuffer, char *UncompressedBuffer, 10974941239SRafael Espindola size_t &UncompressedSize) { 110167ca4aeSGeorge Rimar llvm_unreachable("zlib::uncompress is unavailable"); 11174941239SRafael Espindola } 112167ca4aeSGeorge Rimar Error zlib::uncompress(StringRef InputBuffer, 113857497b9SDavid Blaikie SmallVectorImpl<char> &UncompressedBuffer, 1142fb337e7SAlexey Samsonov size_t UncompressedSize) { 115167ca4aeSGeorge Rimar llvm_unreachable("zlib::uncompress is unavailable"); 1162fb337e7SAlexey Samsonov } 1176ede706dSAlexey Samsonov uint32_t zlib::crc32(StringRef Buffer) { 1186ede706dSAlexey Samsonov llvm_unreachable("zlib::crc32 is unavailable"); 1196ede706dSAlexey Samsonov } 1202fb337e7SAlexey Samsonov #endif 1212fb337e7SAlexey Samsonov 122