diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt index d98d0e10fd..b7b90a8f59 100644 --- a/src/libslic3r/CMakeLists.txt +++ b/src/libslic3r/CMakeLists.txt @@ -126,6 +126,8 @@ add_library(libslic3r STATIC Line.hpp LibraryCheck.cpp LibraryCheck.hpp + LocalesUtils.cpp + LocalesUtils.hpp Model.cpp Model.hpp ModelArrange.hpp diff --git a/src/libslic3r/LocalesUtils.cpp b/src/libslic3r/LocalesUtils.cpp new file mode 100644 index 0000000000..d98145e4b6 --- /dev/null +++ b/src/libslic3r/LocalesUtils.cpp @@ -0,0 +1,59 @@ +#include "LocalesUtils.hpp" + + +namespace Slic3r { + + +CNumericLocalesSetter::CNumericLocalesSetter() +{ +#ifdef _WIN32 + _configthreadlocale(_ENABLE_PER_THREAD_LOCALE); + m_orig_numeric_locale = std::setlocale(LC_NUMERIC, nullptr); + std::setlocale(LC_NUMERIC, "C"); +#else + m_original_locale = uselocale((locale_t)0); + m_new_locale = duplocale(m_original_locale); + m_new_locale = newlocale(LC_NUMERIC_MASK, "C", m_new_locale); + uselocale(m_new_locale); +#endif +} + + + +CNumericLocalesSetter::~CNumericLocalesSetter() +{ +#ifdef _WIN32 + std::setlocale(LC_NUMERIC, m_orig_numeric_locale) +#else + uselocale(m_original_locale); + freelocale(m_new_locale); +#endif +} + + + +bool is_decimal_separator_point() +{ + char str[5] = ""; + sprintf(str, "%.1f", 0.5f); + return str[1] == '.'; +} + +std::string float_to_string_decimal_point(double value, int precision/* = -1*/) +{ + assert(is_decimal_separator_point()); + std::stringstream buf; + if (precision >= 0) + buf << std::fixed << std::setprecision(precision); + buf << value; + return buf.str(); +} + +std::string float_to_string_decimal_point(float value, int precision/* = -1*/) +{ + return float_to_string_decimal_point(double(value), precision); +} + + +} // namespace Slic3r + diff --git a/src/libslic3r/LocalesUtils.hpp b/src/libslic3r/LocalesUtils.hpp new file mode 100644 index 0000000000..74281a1575 --- /dev/null +++ b/src/libslic3r/LocalesUtils.hpp @@ -0,0 +1,47 @@ +#ifndef slic3r_LocalesUtils_hpp_ +#define slic3r_LocalesUtils_hpp_ + +#include +#include +#include +#include + +#ifdef __APPLE__ +#include +#endif + +namespace Slic3r { + +// RAII wrapper that sets LC_NUMERIC to "C" on construction +// and restores the old value on destruction. +class CNumericLocalesSetter { +public: + CNumericLocalesSetter(); + ~CNumericLocalesSetter(); + +private: +#ifdef _WIN32 + std::string m_orig_numeric_locale; +#else + locale_t m_original_locale; + locale_t m_new_locale; +#endif + +}; + +// A function to check that current C locale uses decimal point as a separator. +// Intended mostly for asserts. +bool is_decimal_separator_point(); + + +// A substitute for std::to_string that works according to +// C++ locales, not C locale. Meant to be used when we need +// to be sure that decimal point is used as a separator. +// (We use user C locales and "C" C++ locales in most of the code.) +std::string float_to_string_decimal_point(double value, int precision = -1); +std::string float_to_string_decimal_point(float value, int precision = -1); + + +} // namespace Slic3r + +#endif // slic3r_LocalesUtils_hpp_