246 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			246 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
|   | // 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_ */
 |