123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- // 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 <system_error>
- #include <boost/process/detail/config.hpp>
- #if defined(BOOST_WINDOWS_API)
- #include <boost/process/detail/windows/locale.hpp>
- # elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) \
- || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__HAIKU__)
- #include <codecvt>
- #endif
- #include <locale>
- 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<wchar_t>);
- # 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<wchar_t, char, std::mbstate_t> codecvt_type;
- ///Get a reference to the currently used code converter.
- inline const codecvt_type& codecvt()
- {
- return std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t>>(
- 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<wchar_t> convert(const std::vector<char> & st,
- const ::boost::process::codecvt_type & cvt =
- ::boost::process::codecvt())
- {
- std::vector<wchar_t> 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<char> convert(const std::vector<wchar_t> & st,
- const ::boost::process::codecvt_type & cvt =
- ::boost::process::codecvt())
- {
- std::vector<char> 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_ */
|