aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/restricted/boost/iostreams/src/lzma.cpp
blob: 9376c23d6002389c2ea3f447419886e610e81a19 (plain) (blame)
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
// (C) Copyright Milan Svoboda 2008.
// Originally developed under the fusecompress project.
// Based on bzip2.cpp by:
// (C) Copyright Jonathan Turkanis 2003.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)

// See http://www.boost.org/libs/iostreams for documentation.

// Define BOOST_IOSTREAMS_SOURCE so that <boost/iostreams/detail/config.hpp>
// knows that we are building the library (possibly exporting code), rather
// than using it (possibly importing code).
#define BOOST_IOSTREAMS_SOURCE

#include <lzma.h>

#include <boost/throw_exception.hpp>
#include <boost/iostreams/detail/config/dyn_link.hpp>
#include <boost/iostreams/filter/lzma.hpp>


#ifndef BOOST_IOSTREAMS_LZMA_NO_MULTITHREADED
    #if LZMA_VERSION < 50020002
        #define BOOST_IOSTREAMS_LZMA_NO_MULTITHREADED
    #endif
#endif

namespace boost { namespace iostreams {

namespace lzma {

                    // Compression levels

const uint32_t no_compression       = 0;
const uint32_t best_speed           = 1;
const uint32_t best_compression     = 9;
const uint32_t default_compression  = 2;

                    // Status codes

const int okay                 = LZMA_OK;
const int stream_end           = LZMA_STREAM_END;
const int unsupported_check    = LZMA_UNSUPPORTED_CHECK;
const int mem_error            = LZMA_MEM_ERROR;
const int options_error        = LZMA_OPTIONS_ERROR;
const int data_error           = LZMA_DATA_ERROR;
const int buf_error            = LZMA_BUF_ERROR;
const int prog_error           = LZMA_PROG_ERROR;

                    // Flush codes

const int finish               = LZMA_FINISH;
const int full_flush           = LZMA_FULL_FLUSH;
const int sync_flush           = LZMA_SYNC_FLUSH;
const int run                  = LZMA_RUN;

                    // Code for current OS

} // End namespace lzma.

//------------------Implementation of lzma_error------------------------------//

lzma_error::lzma_error(int error)
    : BOOST_IOSTREAMS_FAILURE("lzma error"), error_(error)
    { }

void lzma_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(int error)
{
    switch (error) {
    case LZMA_OK:
    case LZMA_STREAM_END:
        return;
    case LZMA_MEM_ERROR:
        boost::throw_exception(std::bad_alloc());
    default:
        boost::throw_exception(lzma_error(error));
    }
}

//------------------Implementation of lzma_base-------------------------------//

namespace detail {

lzma_base::lzma_base()
    : stream_(new lzma_stream), level_(lzma::default_compression), threads_(1)
    { }

lzma_base::~lzma_base() { delete static_cast<lzma_stream*>(stream_); }

void lzma_base::before( const char*& src_begin, const char* src_end,
                        char*& dest_begin, char* dest_end )
{
    lzma_stream* s = static_cast<lzma_stream*>(stream_);
    s->next_in = reinterpret_cast<uint8_t*>(const_cast<char*>(src_begin));
    s->avail_in = static_cast<size_t>(src_end - src_begin);
    s->next_out = reinterpret_cast<uint8_t*>(dest_begin);
    s->avail_out= static_cast<size_t>(dest_end - dest_begin);
}

void lzma_base::after(const char*& src_begin, char*& dest_begin, bool)
{
    lzma_stream* s = static_cast<lzma_stream*>(stream_);
    src_begin = const_cast<const char*>(reinterpret_cast<const char*>(s->next_in));
    dest_begin = reinterpret_cast<char*>(s->next_out);
}

int lzma_base::deflate(int action)
{
    return lzma_code(static_cast<lzma_stream*>(stream_), static_cast<lzma_action>(action));
}

int lzma_base::inflate(int action)
{
    return lzma_code(static_cast<lzma_stream*>(stream_), static_cast<lzma_action>(action));
}

void lzma_base::reset(bool compress, bool realloc)
{
    lzma_stream* s = static_cast<lzma_stream*>(stream_);
    lzma_end(s);
    if (realloc)
    {
        init_stream(compress);
    }
}

void lzma_base::do_init
    ( const lzma_params& p, bool compress,
      lzma::alloc_func, lzma::free_func,
      void* )
{

    level_ = p.level;
    threads_ = p.threads;

#ifndef BOOST_IOSTREAMS_LZMA_NO_MULTITHREADED
    if (threads_ == 0) {
        threads_ = lzma_cputhreads();
    }
#endif

    init_stream(compress);
}

void lzma_base::init_stream(bool compress)
{
    lzma_stream* s = static_cast<lzma_stream*>(stream_);

    memset(s, 0, sizeof(*s));

#ifndef BOOST_IOSTREAMS_LZMA_NO_MULTITHREADED
    const lzma_mt opt = { 0, threads_, 0, 1000, level_, NULL, LZMA_CHECK_CRC32 };
#endif

    lzma_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(
        compress ?
#ifdef BOOST_IOSTREAMS_LZMA_NO_MULTITHREADED
            lzma_easy_encoder(s, level_, LZMA_CHECK_CRC32) :
#else
            lzma_stream_encoder_mt(s, &opt) :
#endif
            lzma_stream_decoder(s, 100 * 1024 * 1024, LZMA_CONCATENATED)
    );
}


} // End namespace detail.

//----------------------------------------------------------------------------//

} } // End namespaces iostreams, boost.