1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
|
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* This file is a part of bxzstr (https://github.com/tmaklin/bxzstr)
* Written by Tommi Mäklin (tommi@maklin.fi) */
#if defined(BXZSTR_LZMA_SUPPORT) && (BXZSTR_LZMA_SUPPORT) == 1
#ifndef BXZSTR_LZMA_STREAM_WRAPPER_HPP
#define BXZSTR_LZMA_STREAM_WRAPPER_HPP
#include <lzma.h>
#include <string>
#include <sstream>
#include <exception>
#include "stream_wrapper.hpp"
namespace bxz {
/// Exception class thrown by failed liblzma operations.
class lzmaException : public std::exception {
public:
lzmaException(const lzma_ret ret) : _msg("liblzma: ") {
switch (ret) {
case LZMA_MEM_ERROR:
_msg += "LZMA_MEM_ERROR: ";
break;
case LZMA_OPTIONS_ERROR:
_msg += "LZMA_OPTIONS_ERROR: ";
break;
case LZMA_UNSUPPORTED_CHECK:
_msg += "LZMA_UNSUPPORTED_CHECK: ";
break;
case LZMA_PROG_ERROR:
_msg += "LZMA_PROG_ERROR: ";
break;
case LZMA_BUF_ERROR:
_msg += "LZMA_BUF_ERROR: ";
break;
case LZMA_DATA_ERROR:
_msg += "LZMA_DATA_ERROR: ";
break;
case LZMA_FORMAT_ERROR:
_msg += "LZMA_FORMAT_ERROR: ";
break;
case LZMA_NO_CHECK:
_msg += "LZMA_NO_CHECK: ";
break;
case LZMA_MEMLIMIT_ERROR:
_msg += "LZMA_MEMLIMIT_ERROR: ";
break;
default:
std::ostringstream oss;
oss << ret;
_msg += "[" + oss.str() + "]: ";
break;
}
_msg += ret;
}
lzmaException(const std::string msg) : _msg(msg) {}
const char * what() const noexcept { return _msg.c_str(); }
private:
std::string _msg;
}; // class lzmaException
namespace detail {
class lzma_stream_wrapper : public lzma_stream, public stream_wrapper {
public:
lzma_stream_wrapper(const bool _is_input = true, const int _level = 2, const int _flags = 0)
: lzma_stream(LZMA_STREAM_INIT), is_input(_is_input) {
lzma_ret ret;
if (is_input) {
lzma_stream::avail_in = 0;
lzma_stream::next_in = NULL;
ret = lzma_auto_decoder(this, UINT64_MAX, _flags);
} else {
ret = lzma_easy_encoder(this, _level, LZMA_CHECK_CRC64);
}
if (ret != LZMA_OK) throw lzmaException(ret);
}
~lzma_stream_wrapper() { lzma_end(this); }
int decompress(const int = 0) override {
ret = lzma_code(this, LZMA_RUN);
if (ret != LZMA_OK && ret != LZMA_STREAM_END && ret) throw lzmaException(ret);
return (int)ret;
}
int compress(const int _flags = LZMA_RUN) override {
ret = lzma_code(this, (lzma_action)_flags);
if (ret != LZMA_OK && ret != LZMA_STREAM_END && ret != LZMA_BUF_ERROR)
throw lzmaException(ret);
return (int)ret;
}
bool stream_end() const override { return this->ret == LZMA_STREAM_END; }
bool done() const override { return (this->ret == LZMA_BUF_ERROR || this->stream_end()); }
const uint8_t* next_in() const override { return lzma_stream::next_in; }
long avail_in() const override { return lzma_stream::avail_in; }
uint8_t* next_out() const override { return lzma_stream::next_out; }
long avail_out() const override { return lzma_stream::avail_out; }
void set_next_in(const unsigned char* in) override { lzma_stream::next_in = in; }
void set_avail_in(long in) override { lzma_stream::avail_in = in; }
void set_next_out(const uint8_t* in) override { lzma_stream::next_out = const_cast<uint8_t*>(in); }
void set_avail_out(long in) override { lzma_stream::avail_out = in; }
private:
bool is_input;
lzma_ret ret;
}; // class lzma_stream_wrapper
} // namespace detail
} // namespace bxz
#endif
#endif
|