// Copyright (c) 2016 Klemens D. Morgenstern // Copyright (c) 2008 Beman Dawes // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PROCESS_LOCALE_HPP_ #define BOOST_PROCESS_LOCALE_HPP_ #include #include #if defined(BOOST_WINDOWS_API) #include # elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) \ || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__HAIKU__) #include #endif #include namespace boost { namespace process { namespace detail { class codecvt_category_t : public std::error_category { public: codecvt_category_t() = default; const char* name() const noexcept override {return "codecvt";} std::string message(int ev) const override { std::string str; switch (ev) { case std::codecvt_base::ok: str = "ok"; break; case std::codecvt_base::partial: str = "partial"; break; case std::codecvt_base::error: str = "error"; break; case std::codecvt_base::noconv: str = "noconv"; break; default: str = "unknown error"; } return str; } }; } ///Internally used error cateory for code conversion. inline const std::error_category& codecvt_category() { static const ::boost::process::detail::codecvt_category_t cat; return cat; } namespace detail { //copied from boost.filesystem inline std::locale default_locale() { # if defined(BOOST_WINDOWS_API) std::locale global_loc = std::locale(); return std::locale(global_loc, new boost::process::detail::windows::windows_file_codecvt); # elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) \ || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__HAIKU__) std::locale global_loc = std::locale(); return std::locale(global_loc, new std::codecvt_utf8); # else // Other POSIX // ISO C calls std::locale("") "the locale-specific native environment", and this // locale is the default for many POSIX-based operating systems such as Linux. return std::locale(""); # endif } inline std::locale& process_locale() { static std::locale loc(default_locale()); return loc; } } ///The internally used type for code conversion. typedef std::codecvt codecvt_type; ///Get a reference to the currently used code converter. inline const codecvt_type& codecvt() { return std::use_facet>( detail::process_locale()); } ///Set the locale of the library. inline std::locale imbue(const std::locale& loc) { std::locale temp(detail::process_locale()); detail::process_locale() = loc; return temp; } namespace detail { inline std::size_t convert(const char* from, const char* from_end, wchar_t* to, wchar_t* to_end, const ::boost::process::codecvt_type & cvt = ::boost::process::codecvt()) { std::mbstate_t state = std::mbstate_t(); // perhaps unneeded, but cuts bug reports const char* from_next; wchar_t* to_next; auto res = cvt.in(state, from, from_end, from_next, to, to_end, to_next); if (res != std::codecvt_base::ok) throw process_error(res, ::boost::process::codecvt_category(), "boost::process codecvt to wchar_t"); return to_next - to; } inline std::size_t convert(const wchar_t* from, const wchar_t* from_end, char* to, char* to_end, const ::boost::process::codecvt_type & cvt = ::boost::process::codecvt()) { std::mbstate_t state = std::mbstate_t(); // perhaps unneeded, but cuts bug reports const wchar_t* from_next; char* to_next; std::codecvt_base::result res; if ((res=cvt.out(state, from, from_end, from_next, to, to_end, to_next)) != std::codecvt_base::ok) throw process_error(res, ::boost::process::codecvt_category(), "boost::process codecvt to char"); return to_next - to; } inline std::wstring convert(const std::string & st, const ::boost::process::codecvt_type & cvt = ::boost::process::codecvt()) { std::wstring out(st.size() + 10, ' '); //just to be sure auto sz = convert(st.c_str(), st.c_str() + st.size(), &out.front(), &out.back(), cvt); out.resize(sz); return out; } inline std::string convert(const std::wstring & st, const ::boost::process::codecvt_type & cvt = ::boost::process::codecvt()) { std::string out(st.size() * 2, ' '); //just to be sure auto sz = convert(st.c_str(), st.c_str() + st.size(), &out.front(), &out.back(), cvt); out.resize(sz); return out; } inline std::vector convert(const std::vector & st, const ::boost::process::codecvt_type & cvt = ::boost::process::codecvt()) { std::vector out(st.size() + 10); //just to be sure auto sz = convert(st.data(), st.data() + st.size(), &out.front(), &out.back(), cvt); out.resize(sz); return out; } inline std::vector convert(const std::vector & st, const ::boost::process::codecvt_type & cvt = ::boost::process::codecvt()) { std::vector out(st.size() * 2); //just to be sure auto sz = convert(st.data(), st.data() + st.size(), &out.front(), &out.back(), cvt); out.resize(sz); return out; } inline std::wstring convert(const char *begin, const char* end, const ::boost::process::codecvt_type & cvt = ::boost::process::codecvt()) { auto size = end-begin; std::wstring out(size + 10, ' '); //just to be sure using namespace std; auto sz = convert(begin, end, &out.front(), &out.back(), cvt); out.resize(sz); return out; } inline std::string convert(const wchar_t * begin, const wchar_t *end, const ::boost::process::codecvt_type & cvt = ::boost::process::codecvt()) { auto size = end-begin; std::string out(size * 2, ' '); //just to be sure auto sz = convert(begin, end , &out.front(), &out.back(), cvt); out.resize(sz); return out; } } } } #endif /* BOOST_PROCESS_LOCALE_HPP_ */