Welcome to mirror list, hosted at ThFree Co, Russian Federation.

Zipper.cpp « libslic3r « src - github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: a5b53584d78981b318aa0a0742fbeed97b5f7f8b (plain)
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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
#include <exception>

#include "Zipper.hpp"
#include "miniz_extension.hpp"
#include <boost/log/trivial.hpp>
#include "I18N.hpp"

//! macro used to mark string used at localization,
//! return same string
#define L(s) Slic3r::I18N::translate(s)

#if defined(_MSC_VER) &&  _MSC_VER <= 1800 || __cplusplus < 201103L
    #define SLIC3R_NORETURN
#elif __cplusplus >= 201103L
    #define SLIC3R_NORETURN [[noreturn]]
#endif

namespace Slic3r {

class Zipper::Impl {
public:
    mz_zip_archive arch;
    std::string m_zipname;

    static std::string get_errorstr(mz_zip_error mz_err)
    {
        switch (mz_err)
        {
            case MZ_ZIP_NO_ERROR:
                return "no error";
            case MZ_ZIP_UNDEFINED_ERROR:
                return L("undefined error");
            case MZ_ZIP_TOO_MANY_FILES:
                return L("too many files");
            case MZ_ZIP_FILE_TOO_LARGE:
                return L("file too large");
            case MZ_ZIP_UNSUPPORTED_METHOD:
                return L("unsupported method");
            case MZ_ZIP_UNSUPPORTED_ENCRYPTION:
                return L("unsupported encryption");
            case MZ_ZIP_UNSUPPORTED_FEATURE:
                return L("unsupported feature");
            case MZ_ZIP_FAILED_FINDING_CENTRAL_DIR:
                return L("failed finding central directory");
            case MZ_ZIP_NOT_AN_ARCHIVE:
                return L("not a ZIP archive");
            case MZ_ZIP_INVALID_HEADER_OR_CORRUPTED:
                return L("invalid header or archive is corrupted");
            case MZ_ZIP_UNSUPPORTED_MULTIDISK:
                return L("unsupported multidisk archive");
            case MZ_ZIP_DECOMPRESSION_FAILED:
                return L("decompression failed or archive is corrupted");
            case MZ_ZIP_COMPRESSION_FAILED:
                return L("compression failed");
            case MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE:
                return L("unexpected decompressed size");
            case MZ_ZIP_CRC_CHECK_FAILED:
                return L("CRC-32 check failed");
            case MZ_ZIP_UNSUPPORTED_CDIR_SIZE:
                return L("unsupported central directory size");
            case MZ_ZIP_ALLOC_FAILED:
                return L("allocation failed");
            case MZ_ZIP_FILE_OPEN_FAILED:
                return L("file open failed");
            case MZ_ZIP_FILE_CREATE_FAILED:
                return L("file create failed");
            case MZ_ZIP_FILE_WRITE_FAILED:
                return L("file write failed");
            case MZ_ZIP_FILE_READ_FAILED:
                return L("file read failed");
            case MZ_ZIP_FILE_CLOSE_FAILED:
                return L("file close failed");
            case MZ_ZIP_FILE_SEEK_FAILED:
                return L("file seek failed");
            case MZ_ZIP_FILE_STAT_FAILED:
                return L("file stat failed");
            case MZ_ZIP_INVALID_PARAMETER:
                return L("invalid parameter");
            case MZ_ZIP_INVALID_FILENAME:
                return L("invalid filename");
            case MZ_ZIP_BUF_TOO_SMALL:
                return L("buffer too small");
            case MZ_ZIP_INTERNAL_ERROR:
                return L("internal error");
            case MZ_ZIP_FILE_NOT_FOUND:
                return L("file not found");
            case MZ_ZIP_ARCHIVE_TOO_LARGE:
                return L("archive is too large");
            case MZ_ZIP_VALIDATION_FAILED:
                return L("validation failed");
            case MZ_ZIP_WRITE_CALLBACK_FAILED:
                return L("write calledback failed");
            default:
                break;
        }

        return "unknown error";
    }

    std::string formatted_errorstr() const
    {
        return L("Error with zip archive") + " " + m_zipname + ": " +
               get_errorstr(arch.m_last_error) + "!";
    }

    SLIC3R_NORETURN void blow_up() const
    {
        throw std::runtime_error(formatted_errorstr());
    }

    bool is_alive()
    {
        return arch.m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED;
    }
};

Zipper::Zipper(const std::string &zipfname, e_compression compression)
{
    m_impl.reset(new Impl());

    m_compression = compression;
    m_impl->m_zipname = zipfname;

    memset(&m_impl->arch, 0, sizeof(m_impl->arch));

    if (!open_zip_writer(&m_impl->arch, zipfname)) {
        m_impl->blow_up();
    }
}

Zipper::~Zipper()
{
    if(m_impl->is_alive()) {
        // Flush the current entry if not finished yet.
        try { finish_entry(); } catch(...) {
            BOOST_LOG_TRIVIAL(error) << m_impl->formatted_errorstr();
        }

        if(!mz_zip_writer_finalize_archive(&m_impl->arch))
            BOOST_LOG_TRIVIAL(error) << m_impl->formatted_errorstr();
    }

    // The file should be closed no matter what...
    if(!close_zip_writer(&m_impl->arch))
        BOOST_LOG_TRIVIAL(error) << m_impl->formatted_errorstr();
}

Zipper::Zipper(Zipper &&m):
    m_impl(std::move(m.m_impl)),
    m_data(std::move(m.m_data)),
    m_entry(std::move(m.m_entry)),
    m_compression(m.m_compression) {}

Zipper &Zipper::operator=(Zipper &&m) {
    m_impl = std::move(m.m_impl);
    m_data = std::move(m.m_data);
    m_entry = std::move(m.m_entry);
    m_compression = m.m_compression;
    return *this;
}

void Zipper::add_entry(const std::string &name)
{
    if(!m_impl->is_alive()) return;

    finish_entry(); // finish previous business
    m_entry = name;
}

void Zipper::add_entry(const std::string &name, const uint8_t *data, size_t l)
{
    if(!m_impl->is_alive()) return;

    finish_entry();
    mz_uint cmpr = MZ_NO_COMPRESSION;
    switch (m_compression) {
    case NO_COMPRESSION: cmpr = MZ_NO_COMPRESSION; break;
    case FAST_COMPRESSION: cmpr = MZ_BEST_SPEED; break;
    case TIGHT_COMPRESSION: cmpr = MZ_BEST_COMPRESSION; break;
    }

    if(!mz_zip_writer_add_mem(&m_impl->arch, name.c_str(), data, l, cmpr))
        m_impl->blow_up();

    m_entry.clear();
    m_data.clear();
}

void Zipper::finish_entry()
{
    if(!m_impl->is_alive()) return;

    if(!m_data.empty() && !m_entry.empty()) {
        mz_uint compression = MZ_NO_COMPRESSION;

        switch (m_compression) {
        case NO_COMPRESSION: compression = MZ_NO_COMPRESSION; break;
        case FAST_COMPRESSION: compression = MZ_BEST_SPEED; break;
        case TIGHT_COMPRESSION: compression = MZ_BEST_COMPRESSION; break;
        }

        if(!mz_zip_writer_add_mem(&m_impl->arch, m_entry.c_str(),
                                  m_data.c_str(),
                                  m_data.size(),
                                  compression)) m_impl->blow_up();
    }

    m_data.clear();
    m_entry.clear();
}

void Zipper::finalize()
{
    finish_entry();

    if(m_impl->is_alive()) if(!mz_zip_writer_finalize_archive(&m_impl->arch))
        m_impl->blow_up();
}

const std::string &Zipper::get_filename() const
{
    return m_impl->m_zipname;
}

}