--- /dev/null
+// 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(){}
+ 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_ */