#include <iostream>
#include <string>
#include <vector>
#include <boost/locale.hpp>
namespace yekneb
{
namespace detail
{
namespace string_cast
{
inline bool IsUTF8(const std::locale &loc)
{
std::string locName = loc.name();
if (! locName.empty() && std::string::npos != locName.find("UTF-8"))
{
return true;
}
return false;
}
inline std::string w2s(const std::wstring& ws, const std::locale& loc)
{
typedef std::codecvt<wchar_t, char, std::mbstate_t> converter_type;
typedef std::ctype<wchar_t> wchar_facet;
std::string return_value;
if (ws.empty())
{
return "";
}
if (IsUTF8(loc))
{
return_value = boost::locale::conv::utf_to_utf<char>(ws);
if (! return_value.empty())
{
return return_value;
}
}
const wchar_t* from = ws.c_str();
size_t len = ws.length();
size_t converterMaxLength = 6;
size_t vectorSize = ((len + 6) * converterMaxLength);
if (std::has_facet<converter_type>(loc))
{
const converter_type& converter = std::use_facet<converter_type>(loc);
if (converter.always_noconv())
{
converterMaxLength = converter.max_length();
if (converterMaxLength != 6)
{
vectorSize = ((len + 6) * converterMaxLength);
}
std::mbstate_t state;
const wchar_t* from_next = nullptr;
std::vector<char> to(vectorSize, 0);
std::vector<char>::pointer toPtr = to.data();
std::vector<char>::pointer to_next = nullptr;
const converter_type::result result = converter.out(
state, from, from + len, from_next,
toPtr, toPtr + vectorSize, to_next);
if (
(converter_type::ok == result || converter_type::noconv == result)
&& 0 != toPtr[0]
)
{
return_value.assign(toPtr, to_next);
}
}
}
if (return_value.empty() && std::has_facet<wchar_facet>(loc))
{
std::vector<char> to(vectorSize, 0);
std::vector<char>::pointer toPtr = to.data();
const wchar_facet& facet = std::use_facet<wchar_facet>(loc);
if (facet.narrow(from, from + len, '?', toPtr) != 0)
{
return_value = toPtr;
}
}
return return_value;
}
inline std::wstring s2w(const std::string& s, const std::locale& loc)
{
typedef std::ctype<wchar_t> wchar_facet;
std::wstring return_value;
if (s.empty())
{
return L"";
}
if (std::has_facet<wchar_facet>(loc))
{
std::vector<wchar_t> to(s.size() + 2, 0);
std::vector<wchar_t>::pointer toPtr = to.data();
const wchar_facet& facet = std::use_facet<wchar_facet>(loc);
if (facet.widen(s.c_str(), s.c_str() + s.size(), toPtr) != 0)
{
return_value = to.data();
}
}
return return_value;
}
}
}
template<typename Target, typename Source>
inline Target string_cast(const Source& source)
{
return source;
}
template<>
inline std::wstring string_cast(const std::string& source)
{
std::locale loc;
return ::yekneb::detail::string_cast::s2w(source, loc);
}
template<>
inline std::string string_cast(const std::wstring& source)
{
std::locale loc;
return ::yekneb::detail::string_cast::w2s(source, loc);
}
}
int main()
{
std::string s1("Buenos días.");
std::wstring ws1 = yekneb::string_cast<std::wstring>(s1);
std::wcout << ws1 << L"\n";
std::wstring ws2(L"Buenos días.");
std::string s2 = yekneb::string_cast<std::string>(ws2);
std::cout << s1 << "\n";
return 0;
}