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