2019-03-14 18:07:16 +00:00
|
|
|
#include <exception>
|
|
|
|
|
2020-09-14 14:27:55 +00:00
|
|
|
#include "Exception.hpp"
|
2019-03-14 18:07:16 +00:00
|
|
|
#include "Zipper.hpp"
|
2019-06-03 13:27:46 +00:00
|
|
|
#include "miniz_extension.hpp"
|
2019-03-27 12:22:04 +00:00
|
|
|
#include <boost/log/trivial.hpp>
|
2019-03-15 11:16:05 +00:00
|
|
|
#include "I18N.hpp"
|
|
|
|
|
|
|
|
//! macro used to mark string used at localization,
|
|
|
|
//! return same string
|
|
|
|
#define L(s) Slic3r::I18N::translate(s)
|
|
|
|
|
2019-03-15 11:30:41 +00:00
|
|
|
#if defined(_MSC_VER) && _MSC_VER <= 1800 || __cplusplus < 201103L
|
|
|
|
#define SLIC3R_NORETURN
|
|
|
|
#elif __cplusplus >= 201103L
|
|
|
|
#define SLIC3R_NORETURN [[noreturn]]
|
|
|
|
#endif
|
|
|
|
|
2019-03-14 18:07:16 +00:00
|
|
|
namespace Slic3r {
|
|
|
|
|
2020-04-23 17:12:07 +00:00
|
|
|
class Zipper::Impl: public MZ_Archive {
|
2019-03-14 18:07:16 +00:00
|
|
|
public:
|
2019-03-15 11:30:41 +00:00
|
|
|
std::string m_zipname;
|
2019-03-15 11:16:05 +00:00
|
|
|
|
2019-03-27 12:22:04 +00:00
|
|
|
std::string formatted_errorstr() const
|
|
|
|
{
|
|
|
|
return L("Error with zip archive") + " " + m_zipname + ": " +
|
2020-11-04 08:23:47 +00:00
|
|
|
get_errorstr();
|
2019-03-27 12:22:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SLIC3R_NORETURN void blow_up() const
|
|
|
|
{
|
2020-11-04 08:23:47 +00:00
|
|
|
throw Slic3r::ExportError(formatted_errorstr());
|
2019-03-15 11:16:05 +00:00
|
|
|
}
|
2019-03-28 15:19:30 +00:00
|
|
|
|
|
|
|
bool is_alive()
|
|
|
|
{
|
|
|
|
return arch.m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED;
|
|
|
|
}
|
2019-03-14 18:07:16 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
Zipper::Zipper(const std::string &zipfname, e_compression compression)
|
|
|
|
{
|
|
|
|
m_impl.reset(new Impl());
|
|
|
|
|
2019-03-15 11:30:41 +00:00
|
|
|
m_compression = compression;
|
|
|
|
m_impl->m_zipname = zipfname;
|
|
|
|
|
2019-03-14 18:07:16 +00:00
|
|
|
memset(&m_impl->arch, 0, sizeof(m_impl->arch));
|
|
|
|
|
2019-06-03 13:27:46 +00:00
|
|
|
if (!open_zip_writer(&m_impl->arch, zipfname)) {
|
2019-06-02 17:10:13 +00:00
|
|
|
m_impl->blow_up();
|
|
|
|
}
|
2019-03-14 18:07:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Zipper::~Zipper()
|
|
|
|
{
|
2019-03-28 15:19:30 +00:00
|
|
|
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();
|
2019-03-27 12:22:04 +00:00
|
|
|
}
|
2019-03-28 15:19:30 +00:00
|
|
|
|
|
|
|
// The file should be closed no matter what...
|
2019-06-03 13:27:46 +00:00
|
|
|
if(!close_zip_writer(&m_impl->arch))
|
2019-03-28 15:19:30 +00:00
|
|
|
BOOST_LOG_TRIVIAL(error) << m_impl->formatted_errorstr();
|
2019-03-15 11:16:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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)),
|
2019-03-15 11:30:41 +00:00
|
|
|
m_compression(m.m_compression) {}
|
2019-03-15 11:16:05 +00:00
|
|
|
|
|
|
|
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;
|
2019-03-14 18:07:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Zipper::add_entry(const std::string &name)
|
|
|
|
{
|
2019-03-28 15:19:30 +00:00
|
|
|
if(!m_impl->is_alive()) return;
|
|
|
|
|
2019-03-14 18:07:16 +00:00
|
|
|
finish_entry(); // finish previous business
|
|
|
|
m_entry = name;
|
|
|
|
}
|
|
|
|
|
2020-04-13 10:31:37 +00:00
|
|
|
void Zipper::add_entry(const std::string &name, const void *data, size_t l)
|
2019-03-18 17:02:50 +00:00
|
|
|
{
|
2019-03-28 15:19:30 +00:00
|
|
|
if(!m_impl->is_alive()) return;
|
|
|
|
|
2019-03-18 17:02:50 +00:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2019-03-14 18:07:16 +00:00
|
|
|
void Zipper::finish_entry()
|
|
|
|
{
|
2019-03-28 15:19:30 +00:00
|
|
|
if(!m_impl->is_alive()) return;
|
|
|
|
|
|
|
|
if(!m_data.empty() && !m_entry.empty()) {
|
2019-03-14 18:07:16 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2019-03-15 11:16:05 +00:00
|
|
|
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();
|
2019-03-14 18:07:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
m_data.clear();
|
|
|
|
m_entry.clear();
|
|
|
|
}
|
|
|
|
|
2019-03-28 15:19:30 +00:00
|
|
|
void Zipper::finalize()
|
2019-03-27 12:22:04 +00:00
|
|
|
{
|
|
|
|
finish_entry();
|
|
|
|
|
2019-03-28 15:19:30 +00:00
|
|
|
if(m_impl->is_alive()) if(!mz_zip_writer_finalize_archive(&m_impl->arch))
|
|
|
|
m_impl->blow_up();
|
2019-03-27 12:22:04 +00:00
|
|
|
}
|
|
|
|
|
2019-10-23 15:10:14 +00:00
|
|
|
const std::string &Zipper::get_filename() const
|
|
|
|
{
|
|
|
|
return m_impl->m_zipname;
|
|
|
|
}
|
|
|
|
|
2019-03-14 18:07:16 +00:00
|
|
|
}
|