217477a9ff
Fix compilation on Windows Fix array subscript out of range error in MarchingSquares Fix normals of mesh constructed from slices Improve performance of mesh construction from slices
150 lines
3.7 KiB
C++
150 lines
3.7 KiB
C++
#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_Archive {
|
|
public:
|
|
std::string m_zipname;
|
|
|
|
std::string formatted_errorstr() const
|
|
{
|
|
return L("Error with zip archive") + " " + m_zipname + ": " +
|
|
get_errorstr() + "!";
|
|
}
|
|
|
|
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 void *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;
|
|
}
|
|
|
|
}
|