1284c1978SDimitry Andric //===--- Compression.cpp - Compression implementation ---------------------===//
2284c1978SDimitry Andric //
3284c1978SDimitry Andric // The LLVM Compiler Infrastructure
4284c1978SDimitry Andric //
5284c1978SDimitry Andric // This file is distributed under the University of Illinois Open Source
6284c1978SDimitry Andric // License. See LICENSE.TXT for details.
7284c1978SDimitry Andric //
8284c1978SDimitry Andric //===----------------------------------------------------------------------===//
9284c1978SDimitry Andric //
10284c1978SDimitry Andric // This file implements compression functions.
11284c1978SDimitry Andric //
12284c1978SDimitry Andric //===----------------------------------------------------------------------===//
13284c1978SDimitry Andric
14284c1978SDimitry Andric #include "llvm/Support/Compression.h"
15ff0cc061SDimitry Andric #include "llvm/ADT/SmallVector.h"
16284c1978SDimitry Andric #include "llvm/ADT/StringRef.h"
17284c1978SDimitry Andric #include "llvm/Config/config.h"
18284c1978SDimitry Andric #include "llvm/Support/Compiler.h"
197a7e6055SDimitry Andric #include "llvm/Support/Error.h"
20284c1978SDimitry Andric #include "llvm/Support/ErrorHandling.h"
21284c1978SDimitry Andric #if LLVM_ENABLE_ZLIB == 1 && HAVE_ZLIB_H
22284c1978SDimitry Andric #include <zlib.h>
23284c1978SDimitry Andric #endif
24284c1978SDimitry Andric
25284c1978SDimitry Andric using namespace llvm;
26284c1978SDimitry Andric
27284c1978SDimitry Andric #if LLVM_ENABLE_ZLIB == 1 && HAVE_LIBZ
createError(StringRef Err)287a7e6055SDimitry Andric static Error createError(StringRef Err) {
297a7e6055SDimitry Andric return make_error<StringError>(Err, inconvertibleErrorCode());
307a7e6055SDimitry Andric }
317a7e6055SDimitry Andric
convertZlibCodeToString(int Code)327a7e6055SDimitry Andric static StringRef convertZlibCodeToString(int Code) {
337a7e6055SDimitry Andric switch (Code) {
347a7e6055SDimitry Andric case Z_MEM_ERROR:
357a7e6055SDimitry Andric return "zlib error: Z_MEM_ERROR";
367a7e6055SDimitry Andric case Z_BUF_ERROR:
377a7e6055SDimitry Andric return "zlib error: Z_BUF_ERROR";
387a7e6055SDimitry Andric case Z_STREAM_ERROR:
397a7e6055SDimitry Andric return "zlib error: Z_STREAM_ERROR";
407a7e6055SDimitry Andric case Z_DATA_ERROR:
417a7e6055SDimitry Andric return "zlib error: Z_DATA_ERROR";
427a7e6055SDimitry Andric case Z_OK:
437a7e6055SDimitry Andric default:
447a7e6055SDimitry Andric llvm_unreachable("unknown or unexpected zlib status code");
45284c1978SDimitry Andric }
46284c1978SDimitry Andric }
47284c1978SDimitry Andric
isAvailable()48284c1978SDimitry Andric bool zlib::isAvailable() { return true; }
497a7e6055SDimitry Andric
compress(StringRef InputBuffer,SmallVectorImpl<char> & CompressedBuffer,int Level)507a7e6055SDimitry Andric Error zlib::compress(StringRef InputBuffer,
51*b5893f02SDimitry Andric SmallVectorImpl<char> &CompressedBuffer, int Level) {
52284c1978SDimitry Andric unsigned long CompressedSize = ::compressBound(InputBuffer.size());
53*b5893f02SDimitry Andric CompressedBuffer.reserve(CompressedSize);
54*b5893f02SDimitry Andric int Res =
55*b5893f02SDimitry Andric ::compress2((Bytef *)CompressedBuffer.data(), &CompressedSize,
56*b5893f02SDimitry Andric (const Bytef *)InputBuffer.data(), InputBuffer.size(), Level);
5739d628a0SDimitry Andric // Tell MemorySanitizer that zlib output buffer is fully initialized.
5839d628a0SDimitry Andric // This avoids a false report when running LLVM with uninstrumented ZLib.
5939d628a0SDimitry Andric __msan_unpoison(CompressedBuffer.data(), CompressedSize);
60*b5893f02SDimitry Andric CompressedBuffer.set_size(CompressedSize);
617a7e6055SDimitry Andric return Res ? createError(convertZlibCodeToString(Res)) : Error::success();
62284c1978SDimitry Andric }
63284c1978SDimitry Andric
uncompress(StringRef InputBuffer,char * UncompressedBuffer,size_t & UncompressedSize)647a7e6055SDimitry Andric Error zlib::uncompress(StringRef InputBuffer, char *UncompressedBuffer,
65d88c1a5aSDimitry Andric size_t &UncompressedSize) {
667a7e6055SDimitry Andric int Res =
67d88c1a5aSDimitry Andric ::uncompress((Bytef *)UncompressedBuffer, (uLongf *)&UncompressedSize,
687a7e6055SDimitry Andric (const Bytef *)InputBuffer.data(), InputBuffer.size());
69d88c1a5aSDimitry Andric // Tell MemorySanitizer that zlib output buffer is fully initialized.
70d88c1a5aSDimitry Andric // This avoids a false report when running LLVM with uninstrumented ZLib.
71d88c1a5aSDimitry Andric __msan_unpoison(UncompressedBuffer, UncompressedSize);
727a7e6055SDimitry Andric return Res ? createError(convertZlibCodeToString(Res)) : Error::success();
73d88c1a5aSDimitry Andric }
74d88c1a5aSDimitry Andric
uncompress(StringRef InputBuffer,SmallVectorImpl<char> & UncompressedBuffer,size_t UncompressedSize)757a7e6055SDimitry Andric Error zlib::uncompress(StringRef InputBuffer,
7691bc56edSDimitry Andric SmallVectorImpl<char> &UncompressedBuffer,
77284c1978SDimitry Andric size_t UncompressedSize) {
7891bc56edSDimitry Andric UncompressedBuffer.resize(UncompressedSize);
797a7e6055SDimitry Andric Error E =
80d88c1a5aSDimitry Andric uncompress(InputBuffer, UncompressedBuffer.data(), UncompressedSize);
8191bc56edSDimitry Andric UncompressedBuffer.resize(UncompressedSize);
827a7e6055SDimitry Andric return E;
83284c1978SDimitry Andric }
84284c1978SDimitry Andric
crc32(StringRef Buffer)85f785676fSDimitry Andric uint32_t zlib::crc32(StringRef Buffer) {
86f785676fSDimitry Andric return ::crc32(0, (const Bytef *)Buffer.data(), Buffer.size());
87f785676fSDimitry Andric }
88f785676fSDimitry Andric
89284c1978SDimitry Andric #else
isAvailable()90284c1978SDimitry Andric bool zlib::isAvailable() { return false; }
compress(StringRef InputBuffer,SmallVectorImpl<char> & CompressedBuffer,int Level)917a7e6055SDimitry Andric Error zlib::compress(StringRef InputBuffer,
92*b5893f02SDimitry Andric SmallVectorImpl<char> &CompressedBuffer, int Level) {
937a7e6055SDimitry Andric llvm_unreachable("zlib::compress is unavailable");
94284c1978SDimitry Andric }
uncompress(StringRef InputBuffer,char * UncompressedBuffer,size_t & UncompressedSize)957a7e6055SDimitry Andric Error zlib::uncompress(StringRef InputBuffer, char *UncompressedBuffer,
96d88c1a5aSDimitry Andric size_t &UncompressedSize) {
977a7e6055SDimitry Andric llvm_unreachable("zlib::uncompress is unavailable");
98d88c1a5aSDimitry Andric }
uncompress(StringRef InputBuffer,SmallVectorImpl<char> & UncompressedBuffer,size_t UncompressedSize)997a7e6055SDimitry Andric Error zlib::uncompress(StringRef InputBuffer,
10091bc56edSDimitry Andric SmallVectorImpl<char> &UncompressedBuffer,
101284c1978SDimitry Andric size_t UncompressedSize) {
1027a7e6055SDimitry Andric llvm_unreachable("zlib::uncompress is unavailable");
103284c1978SDimitry Andric }
crc32(StringRef Buffer)104f785676fSDimitry Andric uint32_t zlib::crc32(StringRef Buffer) {
105f785676fSDimitry Andric llvm_unreachable("zlib::crc32 is unavailable");
106f785676fSDimitry Andric }
107284c1978SDimitry Andric #endif
108