7#include "akonadiprivate_debug.h" 
    8#include "compressionstream_p.h" 
   20class LZMAErrorCategory : 
public std::error_category
 
   23    const char *
name() const noexcept
 override 
   27    std::string message(
int ev) 
const noexcept override 
   29        switch (
static_cast<lzma_ret
>(ev)) {
 
   31            return "Operation completed successfully";
 
   33            return "End of stream was reached";
 
   35            return "Input stream has no integrity check";
 
   36        case LZMA_UNSUPPORTED_CHECK:
 
   37            return "Cannot calculate the integrity check";
 
   39            return "Integrity check type is now available";
 
   41            return "Cannot allocate memory";
 
   42        case LZMA_MEMLIMIT_ERROR:
 
   43            return "Memory usage limit was reached";
 
   44        case LZMA_FORMAT_ERROR:
 
   45            return "File format not recognized";
 
   46        case LZMA_OPTIONS_ERROR:
 
   47            return "Invalid or unsupported options";
 
   49            return "Data is corrupt";
 
   51            return "No progress is possible";
 
   53            return "Programming error";
 
   60const LZMAErrorCategory &lzmaErrorCategory()
 
   62    static const LZMAErrorCategory lzmaErrorCategory{};
 
   63    return lzmaErrorCategory;
 
   71struct is_error_code_enum<lzma_ret> : std::true_type {
 
   74std::error_condition make_error_condition(lzma_ret ret)
 
   76    return std::error_condition(
static_cast<int>(ret), lzmaErrorCategory());
 
   81std::error_code make_error_code(lzma_ret e)
 
   83    return {
static_cast<int>(e), lzmaErrorCategory()};
 
   86class Akonadi::Compressor
 
   92            return lzma_auto_decoder(&mStream, 100 * 1024 * 1024 , 0);
 
   94            return lzma_easy_encoder(&mStream, LZMA_PRESET_DEFAULT, LZMA_CHECK_CRC32);
 
   98    void setInputBuffer(
const char *data, qint64 size)
 
  100        mStream.next_in = 
reinterpret_cast<const uint8_t *
>(data);
 
  101        mStream.avail_in = size;
 
  104    void setOutputBuffer(
char *data, qint64 maxSize)
 
  106        mStream.next_out = 
reinterpret_cast<uint8_t *
>(data);
 
  107        mStream.avail_out = maxSize;
 
  110    size_t inputBufferAvailable()
 const 
  112        return mStream.avail_in;
 
  115    size_t outputBufferAvailable()
 const 
  117        return mStream.avail_out;
 
  120    std::error_code finalize()
 
  126    std::error_code inflate()
 
  128        return lzma_code(&mStream, LZMA_RUN);
 
  131    std::error_code deflate(
bool finish)
 
  133        return lzma_code(&mStream, finish ? LZMA_FINISH : LZMA_RUN);
 
  137    lzma_stream mStream = LZMA_STREAM_INIT;
 
  147CompressionStream::~CompressionStream()
 
  149    CompressionStream::close();
 
  152bool CompressionStream::isSequential()
 const 
  157bool CompressionStream::open(OpenMode mode)
 
  160        qCWarning(AKONADIPRIVATE_LOG) << 
"Invalid open mode for CompressionStream.";
 
  164    mCompressor = std::make_unique<Compressor>();
 
  166        qCWarning(AKONADIPRIVATE_LOG) << 
"Failed to initialize LZMA stream coder:" << err.message();
 
  171        mBuffer.resize(BUFSIZ);
 
  172        mCompressor->setOutputBuffer(mBuffer.data(), mBuffer.size());
 
  178void CompressionStream::close()
 
  188    mResult = mCompressor->finalize();
 
  193std::error_code CompressionStream::error()
 const 
  195    return mResult == LZMA_STREAM_END ? LZMA_OK : mResult;
 
  198bool CompressionStream::atEnd()
 const 
  200    return mResult == LZMA_STREAM_END && 
QIODevice::atEnd() && mStream->atEnd();
 
  203qint64 CompressionStream::readData(
char *data, qint64 dataSize)
 
  207    if (mResult == LZMA_STREAM_END) {
 
  209    } 
else if (mResult != LZMA_OK) {
 
  213    mCompressor->setOutputBuffer(data, dataSize);
 
  215    while (dataSize > 0) {
 
  216        if (mCompressor->inputBufferAvailable() == 0) {
 
  217            mBuffer.resize(BUFSIZ);
 
  218            const auto compressedDataRead = mStream->read(mBuffer.data(), mBuffer.size());
 
  220            if (compressedDataRead > 0) {
 
  221                mCompressor->setInputBuffer(mBuffer.data(), compressedDataRead);
 
  227        mResult = mCompressor->inflate();
 
  229        if (mResult != LZMA_OK && mResult != LZMA_STREAM_END) {
 
  230            qCWarning(AKONADIPRIVATE_LOG) << 
"Error while decompressing LZMA stream:" << mResult.message();
 
  234        const auto decompressedDataRead = dataSize - mCompressor->outputBufferAvailable();
 
  235        dataRead += decompressedDataRead;
 
  236        dataSize -= decompressedDataRead;
 
  238        if (mResult == LZMA_STREAM_END) {
 
  239            if (mStream->atEnd()) {
 
  244        mCompressor->setOutputBuffer(data + dataRead, dataSize);
 
  250qint64 CompressionStream::writeData(
const char *data, qint64 dataSize)
 
  252    if (mResult != LZMA_OK) {
 
  256    bool finish = (data == 
nullptr);
 
  258        mCompressor->setInputBuffer(data, dataSize);
 
  261    size_t dataWritten = 0;
 
  263    while (dataSize > 0 || finish) {
 
  264        mResult = mCompressor->deflate(finish);
 
  266        if (mResult != LZMA_OK && mResult != LZMA_STREAM_END) {
 
  267            qCWarning(AKONADIPRIVATE_LOG) << 
"Error while compressing LZMA stream:" << mResult.message();
 
  271        if (mCompressor->inputBufferAvailable() == 0 || (mResult == LZMA_STREAM_END)) {
 
  272            const auto wrote = dataSize - mCompressor->inputBufferAvailable();
 
  274            dataWritten += wrote;
 
  278                mCompressor->setInputBuffer(data + dataWritten, dataSize);
 
  282        if (mCompressor->outputBufferAvailable() == 0 || (mResult == LZMA_STREAM_END) || finish) {
 
  283            const auto toWrite = mBuffer.size() - mCompressor->outputBufferAvailable();
 
  285                const auto writtenSize = mStream->write(mBuffer.constData(), toWrite);
 
  286                if (writtenSize != toWrite) {
 
  287                    qCWarning(AKONADIPRIVATE_LOG) << 
"Failed to write compressed data to output device:" << mStream->errorString();
 
  288                    setErrorString(QStringLiteral(
"Failed to write compressed data to output device."));
 
  293            if (mResult == LZMA_STREAM_END) {
 
  297            mBuffer.resize(BUFSIZ);
 
  298            mCompressor->setOutputBuffer(mBuffer.data(), mBuffer.size());
 
  305bool CompressionStream::isCompressed(
QIODevice *data)
 
  307    constexpr std::array<uchar, 6> magic = {0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00};
 
  314    if (data->
peek(buf, 
sizeof(buf)) != 
sizeof(buf)) {
 
  318    return memcmp(magic.data(), buf, 
sizeof(buf)) == 0;
 
  321#include "moc_compressionstream_p.cpp" 
Helper integration between Akonadi and Qt.
 
QString name(StandardAction id)
 
virtual bool atEnd() const const
 
bool isOpen() const const
 
bool isReadable() const const
 
virtual bool open(QIODeviceBase::OpenMode mode)
 
QByteArray peek(qint64 maxSize)