Files
OrcaSlicer-bambulab/xs/src/libslic3r/utils.cpp
bubnikv 19977edae2 Removed the "Broken croak" support, which was useful on broken
64bit Strawberry perl only. We don't use Strawberry perl anymore,
so this has been removed for clarity.

Added a PerlCallback wrapper to call a Perl subroutine from a C++ code.
2018-05-03 21:45:43 +02:00

335 lines
8.4 KiB
C++

#include "Utils.hpp"
#include <locale>
#include <ctime>
#ifdef WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif
#include <boost/log/core.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/expressions.hpp>
#include <boost/locale.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/date_time/local_time/local_time.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/nowide/fstream.hpp>
#include <boost/nowide/integration/filesystem.hpp>
#include <boost/nowide/convert.hpp>
namespace Slic3r {
static boost::log::trivial::severity_level logSeverity = boost::log::trivial::error;
void set_logging_level(unsigned int level)
{
switch (level) {
// Report fatal errors only.
case 0: logSeverity = boost::log::trivial::fatal; break;
// Report fatal errors and errors.
case 1: logSeverity = boost::log::trivial::error; break;
// Report fatal errors, errors and warnings.
case 2: logSeverity = boost::log::trivial::warning; break;
// Report all errors, warnings and infos.
case 3: logSeverity = boost::log::trivial::info; break;
// Report all errors, warnings, infos and debugging.
case 4: logSeverity = boost::log::trivial::debug; break;
// Report everyting including fine level tracing information.
default: logSeverity = boost::log::trivial::trace; break;
}
boost::log::core::get()->set_filter
(
boost::log::trivial::severity >= logSeverity
);
}
// Force set_logging_level(<=error) after loading of the DLL.
// Switch boost::filesystem to utf8.
static struct RunOnInit {
RunOnInit() {
boost::nowide::nowide_filesystem();
set_logging_level(1);
}
} g_RunOnInit;
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;
}
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)
{
auto file = boost::filesystem::canonical(boost::filesystem::path(g_var_dir) / file_name).make_preferred();
return file.string();
}
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;
}
static std::string g_local_dir;
void set_local_dir(const std::string &dir)
{
g_local_dir = dir;
}
const std::string& localization_dir()
{
return g_local_dir;
}
static std::string g_data_dir;
void set_data_dir(const std::string &dir)
{
g_data_dir = dir;
}
const std::string& data_dir()
{
return g_data_dir;
}
} // namespace Slic3r
#include <xsinit.h>
void
confess_at(const char *file, int line, const char *func,
const char *pat, ...)
{
#ifdef SLIC3RXS
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;
#endif
}
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;
}
}
void PerlCallback::call()
{
if (! m_callback)
return;
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
PUTBACK;
perl_call_sv(SvRV((SV*)m_callback), G_DISCARD);
FREETMPS;
LEAVE;
}
void PerlCallback::call(int i)
{
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;
}
void PerlCallback::call(int i, int j)
{
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;
}
/*
void PerlCallback::call(const std::vector<int> &ints)
{
if (! m_callback)
return;
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
AV* av = newAV();
for (int i : ints)
av_push(av, newSViv(i));
XPUSHs(av);
PUTBACK;
perl_call_sv(SvRV((SV*)m_callback), G_DISCARD);
FREETMPS;
LEAVE;
}
*/
#ifdef WIN32
#ifndef NOMINMAX
# define NOMINMAX
#endif
#include <windows.h>
#endif /* WIN32 */
namespace Slic3r {
// Encode an UTF-8 string to the local code page.
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 */
}
// Encode an 8-bit string from a local code page to UTF-8.
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)
{
static std::locale locale_utf8(boost::locale::generator().generate(""));
return boost::locale::normalize(src, boost::locale::norm_nfc, locale_utf8);
}
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(); }
};
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;
}
unsigned get_current_pid()
{
#ifdef WIN32
return GetCurrentProcessId();
#else
return ::getpid();
#endif
}
}; // namespace Slic3r