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" 19*167ca4aeSGeorge 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 28*167ca4aeSGeorge Rimar static Error createError(StringRef Err) { 29*167ca4aeSGeorge Rimar return make_error<StringError>(Err, inconvertibleErrorCode()); 30*167ca4aeSGeorge Rimar } 31*167ca4aeSGeorge 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 42*167ca4aeSGeorge Rimar static StringRef convertZlibCodeToString(int Code) { 43*167ca4aeSGeorge Rimar switch (Code) { 44*167ca4aeSGeorge Rimar case Z_MEM_ERROR: 45*167ca4aeSGeorge Rimar return "zlib error: Z_MEM_ERROR"; 46*167ca4aeSGeorge Rimar case Z_BUF_ERROR: 47*167ca4aeSGeorge Rimar return "zlib error: Z_BUF_ERROR"; 48*167ca4aeSGeorge Rimar case Z_STREAM_ERROR: 49*167ca4aeSGeorge Rimar return "zlib error: Z_STREAM_ERROR"; 50*167ca4aeSGeorge Rimar case Z_DATA_ERROR: 51*167ca4aeSGeorge Rimar return "zlib error: Z_DATA_ERROR"; 52*167ca4aeSGeorge Rimar case Z_OK: 53*167ca4aeSGeorge Rimar default: 54*167ca4aeSGeorge Rimar llvm_unreachable("unknown or unexpected zlib status code"); 552fb337e7SAlexey Samsonov } 562fb337e7SAlexey Samsonov } 572fb337e7SAlexey Samsonov 582fb337e7SAlexey Samsonov bool zlib::isAvailable() { return true; } 59*167ca4aeSGeorge Rimar 60*167ca4aeSGeorge Rimar Error zlib::compress(StringRef InputBuffer, 61857497b9SDavid Blaikie SmallVectorImpl<char> &CompressedBuffer, 622fb337e7SAlexey Samsonov CompressionLevel Level) { 632fb337e7SAlexey Samsonov unsigned long CompressedSize = ::compressBound(InputBuffer.size()); 64857497b9SDavid Blaikie CompressedBuffer.resize(CompressedSize); 652fb337e7SAlexey Samsonov int CLevel = encodeZlibCompressionLevel(Level); 66*167ca4aeSGeorge Rimar int Res = ::compress2((Bytef *)CompressedBuffer.data(), &CompressedSize, 67*167ca4aeSGeorge Rimar (const Bytef *)InputBuffer.data(), InputBuffer.size(), 68*167ca4aeSGeorge 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); 72857497b9SDavid Blaikie CompressedBuffer.resize(CompressedSize); 73*167ca4aeSGeorge Rimar return Res ? createError(convertZlibCodeToString(Res)) : Error::success(); 742fb337e7SAlexey Samsonov } 752fb337e7SAlexey Samsonov 76*167ca4aeSGeorge Rimar Error zlib::uncompress(StringRef InputBuffer, char *UncompressedBuffer, 7746cdcb03SRafael Espindola size_t &UncompressedSize) { 78*167ca4aeSGeorge Rimar int Res = 7946cdcb03SRafael Espindola ::uncompress((Bytef *)UncompressedBuffer, (uLongf *)&UncompressedSize, 80*167ca4aeSGeorge 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); 84*167ca4aeSGeorge Rimar return Res ? createError(convertZlibCodeToString(Res)) : Error::success(); 8546cdcb03SRafael Espindola } 8646cdcb03SRafael Espindola 87*167ca4aeSGeorge Rimar Error zlib::uncompress(StringRef InputBuffer, 88a505f247SDavid Blaikie SmallVectorImpl<char> &UncompressedBuffer, 892fb337e7SAlexey Samsonov size_t UncompressedSize) { 90a505f247SDavid Blaikie UncompressedBuffer.resize(UncompressedSize); 91*167ca4aeSGeorge Rimar Error E = 9246cdcb03SRafael Espindola uncompress(InputBuffer, UncompressedBuffer.data(), UncompressedSize); 93a505f247SDavid Blaikie UncompressedBuffer.resize(UncompressedSize); 94*167ca4aeSGeorge 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; } 103*167ca4aeSGeorge Rimar Error zlib::compress(StringRef InputBuffer, 104857497b9SDavid Blaikie SmallVectorImpl<char> &CompressedBuffer, 1052fb337e7SAlexey Samsonov CompressionLevel Level) { 106*167ca4aeSGeorge Rimar llvm_unreachable("zlib::compress is unavailable"); 1072fb337e7SAlexey Samsonov } 108*167ca4aeSGeorge Rimar Error zlib::uncompress(StringRef InputBuffer, char *UncompressedBuffer, 10974941239SRafael Espindola size_t &UncompressedSize) { 110*167ca4aeSGeorge Rimar llvm_unreachable("zlib::uncompress is unavailable"); 11174941239SRafael Espindola } 112*167ca4aeSGeorge Rimar Error zlib::uncompress(StringRef InputBuffer, 113857497b9SDavid Blaikie SmallVectorImpl<char> &UncompressedBuffer, 1142fb337e7SAlexey Samsonov size_t UncompressedSize) { 115*167ca4aeSGeorge 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