2018-05-03 19:45:43 +00:00
|
|
|
#include "Utils.hpp"
|
2018-06-20 11:57:37 +00:00
|
|
|
#include "I18N.hpp"
|
2018-05-03 19:45:43 +00:00
|
|
|
|
2017-08-03 15:31:31 +00:00
|
|
|
#include <locale>
|
2017-10-30 17:15:41 +00:00
|
|
|
#include <ctime>
|
2017-08-03 15:31:31 +00:00
|
|
|
|
2018-04-20 09:05:00 +00:00
|
|
|
#ifdef WIN32
|
|
|
|
#include <windows.h>
|
|
|
|
#else
|
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
|
|
|
|
2016-12-12 18:13:33 +00:00
|
|
|
#include <boost/log/core.hpp>
|
|
|
|
#include <boost/log/trivial.hpp>
|
|
|
|
#include <boost/log/expressions.hpp>
|
|
|
|
|
2017-08-03 15:31:31 +00:00
|
|
|
#include <boost/locale.hpp>
|
|
|
|
|
2017-10-25 10:53:31 +00:00
|
|
|
#include <boost/algorithm/string/predicate.hpp>
|
2017-10-30 17:15:41 +00:00
|
|
|
#include <boost/date_time/local_time/local_time.hpp>
|
2017-10-17 18:00:15 +00:00
|
|
|
#include <boost/filesystem.hpp>
|
2017-12-21 15:56:33 +00:00
|
|
|
#include <boost/filesystem/path.hpp>
|
|
|
|
#include <boost/nowide/fstream.hpp>
|
2017-08-03 15:31:31 +00:00
|
|
|
#include <boost/nowide/integration/filesystem.hpp>
|
|
|
|
#include <boost/nowide/convert.hpp>
|
|
|
|
|
2016-12-12 18:13:33 +00:00
|
|
|
namespace Slic3r {
|
|
|
|
|
2017-03-03 13:38:25 +00:00
|
|
|
static boost::log::trivial::severity_level logSeverity = boost::log::trivial::error;
|
2016-12-12 18:13:33 +00:00
|
|
|
|
|
|
|
void set_logging_level(unsigned int level)
|
|
|
|
{
|
|
|
|
switch (level) {
|
2017-03-03 11:53:05 +00:00
|
|
|
// Report fatal errors only.
|
2016-12-12 18:13:33 +00:00
|
|
|
case 0: logSeverity = boost::log::trivial::fatal; break;
|
2017-03-03 11:53:05 +00:00
|
|
|
// Report fatal errors and errors.
|
2016-12-12 18:13:33 +00:00
|
|
|
case 1: logSeverity = boost::log::trivial::error; break;
|
2017-03-03 11:53:05 +00:00
|
|
|
// Report fatal errors, errors and warnings.
|
2016-12-12 18:13:33 +00:00
|
|
|
case 2: logSeverity = boost::log::trivial::warning; break;
|
2017-03-03 11:53:05 +00:00
|
|
|
// Report all errors, warnings and infos.
|
2016-12-12 18:13:33 +00:00
|
|
|
case 3: logSeverity = boost::log::trivial::info; break;
|
2017-03-03 11:53:05 +00:00
|
|
|
// Report all errors, warnings, infos and debugging.
|
2016-12-12 18:13:33 +00:00
|
|
|
case 4: logSeverity = boost::log::trivial::debug; break;
|
2017-03-03 11:53:05 +00:00
|
|
|
// Report everyting including fine level tracing information.
|
2016-12-12 18:13:33 +00:00
|
|
|
default: logSeverity = boost::log::trivial::trace; break;
|
|
|
|
}
|
|
|
|
|
|
|
|
boost::log::core::get()->set_filter
|
|
|
|
(
|
|
|
|
boost::log::trivial::severity >= logSeverity
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2017-03-03 13:38:25 +00:00
|
|
|
// Force set_logging_level(<=error) after loading of the DLL.
|
2017-08-03 15:31:31 +00:00
|
|
|
// Switch boost::filesystem to utf8.
|
|
|
|
static struct RunOnInit {
|
|
|
|
RunOnInit() {
|
|
|
|
boost::nowide::nowide_filesystem();
|
|
|
|
set_logging_level(1);
|
|
|
|
}
|
|
|
|
} g_RunOnInit;
|
2017-03-03 13:38:25 +00:00
|
|
|
|
2017-03-03 11:53:05 +00:00
|
|
|
void trace(unsigned int level, const char *message)
|
|
|
|
{
|
|
|
|
boost::log::trivial::severity_level severity = boost::log::trivial::trace;
|
|
|
|
switch (level) {
|
|
|
|
// Report fatal errors only.
|
|
|
|
case 0: severity = boost::log::trivial::fatal; break;
|
|
|
|
// Report fatal errors and errors.
|
|
|
|
case 1: severity = boost::log::trivial::error; break;
|
|
|
|
// Report fatal errors, errors and warnings.
|
|
|
|
case 2: severity = boost::log::trivial::warning; break;
|
|
|
|
// Report all errors, warnings and infos.
|
|
|
|
case 3: severity = boost::log::trivial::info; break;
|
|
|
|
// Report all errors, warnings, infos and debugging.
|
|
|
|
case 4: severity = boost::log::trivial::debug; break;
|
|
|
|
// Report everyting including fine level tracing information.
|
|
|
|
default: severity = boost::log::trivial::trace; break;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOST_LOG_STREAM_WITH_PARAMS(::boost::log::trivial::logger::get(),\
|
|
|
|
(::boost::log::keywords::severity = severity)) << message;
|
|
|
|
}
|
|
|
|
|
2017-10-17 18:00:15 +00:00
|
|
|
static std::string g_var_dir;
|
|
|
|
|
|
|
|
void set_var_dir(const std::string &dir)
|
|
|
|
{
|
|
|
|
g_var_dir = dir;
|
|
|
|
}
|
|
|
|
|
|
|
|
const std::string& var_dir()
|
|
|
|
{
|
|
|
|
return g_var_dir;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string var(const std::string &file_name)
|
|
|
|
{
|
2018-05-23 11:19:25 +00:00
|
|
|
auto file = (boost::filesystem::path(g_var_dir) / file_name).make_preferred();
|
2017-10-17 18:00:15 +00:00
|
|
|
return file.string();
|
|
|
|
}
|
|
|
|
|
2017-12-10 12:19:44 +00:00
|
|
|
static std::string g_resources_dir;
|
|
|
|
|
|
|
|
void set_resources_dir(const std::string &dir)
|
|
|
|
{
|
|
|
|
g_resources_dir = dir;
|
|
|
|
}
|
|
|
|
|
|
|
|
const std::string& resources_dir()
|
|
|
|
{
|
|
|
|
return g_resources_dir;
|
|
|
|
}
|
|
|
|
|
2018-02-12 07:57:32 +00:00
|
|
|
static std::string g_local_dir;
|
|
|
|
|
|
|
|
void set_local_dir(const std::string &dir)
|
|
|
|
{
|
|
|
|
g_local_dir = dir;
|
|
|
|
}
|
|
|
|
|
|
|
|
const std::string& localization_dir()
|
2018-02-07 16:13:52 +00:00
|
|
|
{
|
2018-02-12 07:57:32 +00:00
|
|
|
return g_local_dir;
|
2018-02-07 16:13:52 +00:00
|
|
|
}
|
|
|
|
|
2018-06-20 11:57:37 +00:00
|
|
|
// Translate function callback, to call wxWidgets translate function to convert non-localized UTF8 string to a localized one.
|
2018-06-20 16:33:46 +00:00
|
|
|
Slic3r::I18N::translate_fn_type Slic3r::I18N::translate_fn = nullptr;
|
2018-06-20 11:57:37 +00:00
|
|
|
|
2017-10-25 10:53:31 +00:00
|
|
|
static std::string g_data_dir;
|
|
|
|
|
|
|
|
void set_data_dir(const std::string &dir)
|
|
|
|
{
|
2018-04-13 13:08:58 +00:00
|
|
|
g_data_dir = dir;
|
2017-10-25 10:53:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const std::string& data_dir()
|
|
|
|
{
|
|
|
|
return g_data_dir;
|
|
|
|
}
|
|
|
|
|
2016-12-12 18:13:33 +00:00
|
|
|
} // namespace Slic3r
|
|
|
|
|
2015-12-07 23:39:54 +00:00
|
|
|
#include <xsinit.h>
|
2013-09-09 19:40:57 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
confess_at(const char *file, int line, const char *func,
|
|
|
|
const char *pat, ...)
|
|
|
|
{
|
2013-09-13 12:48:40 +00:00
|
|
|
#ifdef SLIC3RXS
|
2013-09-09 19:40:57 +00:00
|
|
|
va_list args;
|
|
|
|
SV *error_sv = newSVpvf("Error in function %s at %s:%d: ", func,
|
|
|
|
file, line);
|
|
|
|
|
|
|
|
va_start(args, pat);
|
|
|
|
sv_vcatpvf(error_sv, pat, &args);
|
|
|
|
va_end(args);
|
|
|
|
|
|
|
|
sv_catpvn(error_sv, "\n\t", 2);
|
|
|
|
|
|
|
|
dSP;
|
|
|
|
ENTER;
|
|
|
|
SAVETMPS;
|
|
|
|
PUSHMARK(SP);
|
|
|
|
XPUSHs( sv_2mortal(error_sv) );
|
|
|
|
PUTBACK;
|
|
|
|
call_pv("Carp::confess", G_DISCARD);
|
|
|
|
FREETMPS;
|
|
|
|
LEAVE;
|
2013-09-13 12:48:40 +00:00
|
|
|
#endif
|
2013-09-09 19:40:57 +00:00
|
|
|
}
|
2016-11-08 09:49:32 +00:00
|
|
|
|
2018-05-03 19:45:43 +00:00
|
|
|
void PerlCallback::register_callback(void *sv)
|
|
|
|
{
|
|
|
|
if (! SvROK((SV*)sv) || SvTYPE(SvRV((SV*)sv)) != SVt_PVCV)
|
|
|
|
croak("Not a Callback %_ for PerlFunction", (SV*)sv);
|
|
|
|
if (m_callback)
|
|
|
|
SvSetSV((SV*)m_callback, (SV*)sv);
|
|
|
|
else
|
|
|
|
m_callback = newSVsv((SV*)sv);
|
|
|
|
}
|
|
|
|
|
|
|
|
void PerlCallback::deregister_callback()
|
|
|
|
{
|
|
|
|
if (m_callback) {
|
|
|
|
sv_2mortal((SV*)m_callback);
|
|
|
|
m_callback = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-29 11:54:34 +00:00
|
|
|
void PerlCallback::call() const
|
2018-05-03 19:45:43 +00:00
|
|
|
{
|
|
|
|
if (! m_callback)
|
|
|
|
return;
|
|
|
|
dSP;
|
|
|
|
ENTER;
|
|
|
|
SAVETMPS;
|
|
|
|
PUSHMARK(SP);
|
|
|
|
PUTBACK;
|
|
|
|
perl_call_sv(SvRV((SV*)m_callback), G_DISCARD);
|
|
|
|
FREETMPS;
|
|
|
|
LEAVE;
|
|
|
|
}
|
|
|
|
|
2018-05-29 11:54:34 +00:00
|
|
|
void PerlCallback::call(int i) const
|
2018-05-03 19:45:43 +00:00
|
|
|
{
|
|
|
|
if (! m_callback)
|
|
|
|
return;
|
|
|
|
dSP;
|
|
|
|
ENTER;
|
|
|
|
SAVETMPS;
|
|
|
|
PUSHMARK(SP);
|
|
|
|
XPUSHs(sv_2mortal(newSViv(i)));
|
|
|
|
PUTBACK;
|
|
|
|
perl_call_sv(SvRV((SV*)m_callback), G_DISCARD);
|
|
|
|
FREETMPS;
|
|
|
|
LEAVE;
|
|
|
|
}
|
|
|
|
|
2018-05-29 11:54:34 +00:00
|
|
|
void PerlCallback::call(int i, int j) const
|
2018-05-03 19:45:43 +00:00
|
|
|
{
|
|
|
|
if (! m_callback)
|
|
|
|
return;
|
|
|
|
dSP;
|
|
|
|
ENTER;
|
|
|
|
SAVETMPS;
|
|
|
|
PUSHMARK(SP);
|
|
|
|
XPUSHs(sv_2mortal(newSViv(i)));
|
|
|
|
XPUSHs(sv_2mortal(newSViv(j)));
|
|
|
|
PUTBACK;
|
|
|
|
perl_call_sv(SvRV((SV*)m_callback), G_DISCARD);
|
|
|
|
FREETMPS;
|
|
|
|
LEAVE;
|
|
|
|
}
|
|
|
|
|
2018-05-31 14:04:59 +00:00
|
|
|
void PerlCallback::call(const std::vector<int>& ints) const
|
2018-05-03 19:45:43 +00:00
|
|
|
{
|
|
|
|
if (! m_callback)
|
|
|
|
return;
|
|
|
|
dSP;
|
|
|
|
ENTER;
|
|
|
|
SAVETMPS;
|
|
|
|
PUSHMARK(SP);
|
|
|
|
for (int i : ints)
|
2018-05-31 14:04:59 +00:00
|
|
|
{
|
|
|
|
XPUSHs(sv_2mortal(newSViv(i)));
|
|
|
|
}
|
2018-05-03 19:45:43 +00:00
|
|
|
PUTBACK;
|
|
|
|
perl_call_sv(SvRV((SV*)m_callback), G_DISCARD);
|
|
|
|
FREETMPS;
|
|
|
|
LEAVE;
|
|
|
|
}
|
2017-08-03 17:49:41 +00:00
|
|
|
|
2018-09-07 12:21:04 +00:00
|
|
|
void PerlCallback::call(double a) const
|
2018-06-18 13:07:17 +00:00
|
|
|
{
|
|
|
|
if (!m_callback)
|
|
|
|
return;
|
|
|
|
dSP;
|
|
|
|
ENTER;
|
|
|
|
SAVETMPS;
|
|
|
|
PUSHMARK(SP);
|
2018-09-07 12:21:04 +00:00
|
|
|
XPUSHs(sv_2mortal(newSVnv(a)));
|
2018-06-18 13:07:17 +00:00
|
|
|
PUTBACK;
|
|
|
|
perl_call_sv(SvRV((SV*)m_callback), G_DISCARD);
|
|
|
|
FREETMPS;
|
|
|
|
LEAVE;
|
|
|
|
}
|
|
|
|
|
2018-06-22 09:19:38 +00:00
|
|
|
void PerlCallback::call(double a, double b) const
|
2018-06-07 09:18:28 +00:00
|
|
|
{
|
|
|
|
if (!m_callback)
|
|
|
|
return;
|
|
|
|
dSP;
|
|
|
|
ENTER;
|
|
|
|
SAVETMPS;
|
|
|
|
PUSHMARK(SP);
|
2018-06-22 09:19:38 +00:00
|
|
|
XPUSHs(sv_2mortal(newSVnv(a)));
|
|
|
|
XPUSHs(sv_2mortal(newSVnv(b)));
|
|
|
|
PUTBACK;
|
|
|
|
perl_call_sv(SvRV((SV*)m_callback), G_DISCARD);
|
2018-09-07 12:21:04 +00:00
|
|
|
FREETMPS;
|
|
|
|
LEAVE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PerlCallback::call(double a, double b, double c) const
|
|
|
|
{
|
|
|
|
if (!m_callback)
|
|
|
|
return;
|
|
|
|
dSP;
|
|
|
|
ENTER;
|
|
|
|
SAVETMPS;
|
|
|
|
PUSHMARK(SP);
|
|
|
|
XPUSHs(sv_2mortal(newSVnv(a)));
|
|
|
|
XPUSHs(sv_2mortal(newSVnv(b)));
|
|
|
|
XPUSHs(sv_2mortal(newSVnv(c)));
|
|
|
|
PUTBACK;
|
|
|
|
perl_call_sv(SvRV((SV*)m_callback), G_DISCARD);
|
2018-06-22 09:19:38 +00:00
|
|
|
FREETMPS;
|
|
|
|
LEAVE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PerlCallback::call(double a, double b, double c, double d) const
|
|
|
|
{
|
|
|
|
if (!m_callback)
|
|
|
|
return;
|
|
|
|
dSP;
|
|
|
|
ENTER;
|
|
|
|
SAVETMPS;
|
|
|
|
PUSHMARK(SP);
|
|
|
|
XPUSHs(sv_2mortal(newSVnv(a)));
|
|
|
|
XPUSHs(sv_2mortal(newSVnv(b)));
|
|
|
|
XPUSHs(sv_2mortal(newSVnv(c)));
|
|
|
|
XPUSHs(sv_2mortal(newSVnv(d)));
|
2018-06-07 09:18:28 +00:00
|
|
|
PUTBACK;
|
|
|
|
perl_call_sv(SvRV((SV*)m_callback), G_DISCARD);
|
|
|
|
FREETMPS;
|
|
|
|
LEAVE;
|
|
|
|
}
|
2018-06-08 07:40:00 +00:00
|
|
|
|
|
|
|
void PerlCallback::call(bool b) const
|
|
|
|
{
|
|
|
|
call(b ? 1 : 0);
|
|
|
|
}
|
2018-06-07 09:18:28 +00:00
|
|
|
|
2017-08-03 17:49:41 +00:00
|
|
|
#ifdef WIN32
|
|
|
|
#ifndef NOMINMAX
|
|
|
|
# define NOMINMAX
|
|
|
|
#endif
|
|
|
|
#include <windows.h>
|
|
|
|
#endif /* WIN32 */
|
|
|
|
|
|
|
|
namespace Slic3r {
|
|
|
|
|
2017-12-14 12:47:22 +00:00
|
|
|
// Encode an UTF-8 string to the local code page.
|
2017-08-03 17:49:41 +00:00
|
|
|
std::string encode_path(const char *src)
|
|
|
|
{
|
|
|
|
#ifdef WIN32
|
|
|
|
// Convert the source utf8 encoded string to a wide string.
|
|
|
|
std::wstring wstr_src = boost::nowide::widen(src);
|
|
|
|
if (wstr_src.length() == 0)
|
|
|
|
return std::string();
|
|
|
|
// Convert a wide string to a local code page.
|
|
|
|
int size_needed = ::WideCharToMultiByte(0, 0, wstr_src.data(), (int)wstr_src.size(), nullptr, 0, nullptr, nullptr);
|
|
|
|
std::string str_dst(size_needed, 0);
|
|
|
|
::WideCharToMultiByte(0, 0, wstr_src.data(), (int)wstr_src.size(), const_cast<char*>(str_dst.data()), size_needed, nullptr, nullptr);
|
|
|
|
return str_dst;
|
|
|
|
#else /* WIN32 */
|
|
|
|
return src;
|
|
|
|
#endif /* WIN32 */
|
|
|
|
}
|
|
|
|
|
2017-12-14 12:47:22 +00:00
|
|
|
// Encode an 8-bit string from a local code page to UTF-8.
|
2017-08-03 17:49:41 +00:00
|
|
|
std::string decode_path(const char *src)
|
|
|
|
{
|
|
|
|
#ifdef WIN32
|
|
|
|
int len = int(strlen(src));
|
|
|
|
if (len == 0)
|
|
|
|
return std::string();
|
|
|
|
// Convert the string encoded using the local code page to a wide string.
|
|
|
|
int size_needed = ::MultiByteToWideChar(0, 0, src, len, nullptr, 0);
|
|
|
|
std::wstring wstr_dst(size_needed, 0);
|
|
|
|
::MultiByteToWideChar(0, 0, src, len, const_cast<wchar_t*>(wstr_dst.data()), size_needed);
|
|
|
|
// Convert a wide string to utf8.
|
|
|
|
return boost::nowide::narrow(wstr_dst.c_str());
|
|
|
|
#else /* WIN32 */
|
|
|
|
return src;
|
|
|
|
#endif /* WIN32 */
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string normalize_utf8_nfc(const char *src)
|
|
|
|
{
|
2017-11-02 15:21:34 +00:00
|
|
|
static std::locale locale_utf8(boost::locale::generator().generate(""));
|
2017-08-03 17:49:41 +00:00
|
|
|
return boost::locale::normalize(src, boost::locale::norm_nfc, locale_utf8);
|
|
|
|
}
|
|
|
|
|
2017-12-21 15:56:33 +00:00
|
|
|
namespace PerlUtils {
|
|
|
|
// Get a file name including the extension.
|
|
|
|
std::string path_to_filename(const char *src) { return boost::filesystem::path(src).filename().string(); }
|
|
|
|
// Get a file name without the extension.
|
|
|
|
std::string path_to_stem(const char *src) { return boost::filesystem::path(src).stem().string(); }
|
|
|
|
// Get just the extension.
|
|
|
|
std::string path_to_extension(const char *src) { return boost::filesystem::path(src).extension().string(); }
|
|
|
|
// Get a directory without the trailing slash.
|
|
|
|
std::string path_to_parent_path(const char *src) { return boost::filesystem::path(src).parent_path().string(); }
|
|
|
|
};
|
|
|
|
|
2017-10-30 17:15:41 +00:00
|
|
|
std::string timestamp_str()
|
|
|
|
{
|
|
|
|
const auto now = boost::posix_time::second_clock::local_time();
|
|
|
|
char buf[2048];
|
|
|
|
sprintf(buf, "on %04d-%02d-%02d at %02d:%02d:%02d",
|
|
|
|
// Local date in an ANSII format.
|
|
|
|
int(now.date().year()), int(now.date().month()), int(now.date().day()),
|
|
|
|
int(now.time_of_day().hours()), int(now.time_of_day().minutes()), int(now.time_of_day().seconds()));
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
2018-04-20 09:05:00 +00:00
|
|
|
unsigned get_current_pid()
|
|
|
|
{
|
|
|
|
#ifdef WIN32
|
|
|
|
return GetCurrentProcessId();
|
|
|
|
#else
|
|
|
|
return ::getpid();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2018-07-23 12:39:50 +00:00
|
|
|
std::string xml_escape(std::string text)
|
|
|
|
{
|
|
|
|
std::string::size_type pos = 0;
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
pos = text.find_first_of("\"\'&<>", pos);
|
|
|
|
if (pos == std::string::npos)
|
|
|
|
break;
|
|
|
|
|
|
|
|
std::string replacement;
|
|
|
|
switch (text[pos])
|
|
|
|
{
|
|
|
|
case '\"': replacement = """; break;
|
|
|
|
case '\'': replacement = "'"; break;
|
|
|
|
case '&': replacement = "&"; break;
|
|
|
|
case '<': replacement = "<"; break;
|
|
|
|
case '>': replacement = ">"; break;
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
|
|
|
|
text.replace(pos, 1, replacement);
|
|
|
|
pos += replacement.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
return text;
|
|
|
|
}
|
|
|
|
|
2017-08-03 17:49:41 +00:00
|
|
|
}; // namespace Slic3r
|