246 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			246 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| // 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
 | |
|     // Return a default locale object.
 | |
|     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_ */
 |